• Golang 字符串


    1. Golang 字符串

    1.1. 基础概念

    ASCII 是英文"American Standard Code for Information Interchange"的缩写,中文译为美国信息交换标准代码,它是由美国国家标准学会 (ANSI) 制定的单字节字符编码方案,它使用单个字节 (byte) 的二进制数来编码一个字符。

    Unicode 编码规范为世界上现存的所有自然语言中的每一个字符,都设定了一个唯一的二进制编码。它以 ASCII 编码集为出发点,并突破了 ASCII 只能对拉丁字母进行编码的限制。Unicode 编码规范通常使用十六进制表示法来表示 Unicode 代码的整数值,并提供了三种不同的编码格式,即:UTF-8、UTF-16 和 UTF-32。

    UTF-8 以 8 个比特(一个字节)作为一个编码单元,它是一种可变宽的编码方案,它会用一个或多个字节的二进制数来表示某个字符,最多使用四个字节。对于一个英文字符,它仅用一个字节的二进制数就可以表示,而对于一个中文字符,它需要使用三个字节才能够表示。rune 是 Go 语言特有的一个基本数据类型,它的一个值就代表一个 Unicode 字符,比如’吕’、‘M’。一个 rune 类型的值会由四个字节宽度的空间来存储,它的存储空间总是能够存下一个 UTF-8 编码值。

    1.2. 字符串编码

    一个 rune 类型的值在底层其实就是一个 UTF-8 编码值,前者是(便于我们人类理解的)外部展现,后者是(便于计算机系统理解的)内在表达,请看下面代码:

    func main() {
    	str := "Go 爱好者"
    	fmt.Printf("The string: %q\n", str)
    	fmt.Printf("runes(char): %q\n", []rune(str))   //['G' 'o' '爱' '好' '者']
    	fmt.Printf("runes(hex): %x\n", []rune(str))    //[47 6f 7231 597d 8005]
    	fmt.Printf("bytes(hex): [% x]\n", []byte(str)) //[47 6f e7 88 b1 e5 a5 bd e8 80 85]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    对于第 3 行输出,前面解释的比较清楚,就不赘述。对于第 4 行输出,就是通过 UTF-8 编码,3 个字节的 16 进制展现。第 5 行输出,把每个字符的 UTF-8 编码值都拆成相应的字节序列。

    一句话总结一下:一个 string 类型的值在底层就是一个能够表达若干个 UTF-8 编码值的字节序列。

    1.3. 遍历字符串

    range 遍历:

    func main() {
    	str := "Go 爱好者"
    	fmt.Printf("range 遍历:\n")
    	for i, c := range str {
    		fmt.Printf("%d: %q [% x]\n", i, c, []byte(string(c)))
    	}
    	fmt.Printf("for 遍历:\n")
    	for i := 0; i < len(str); i++ {
    		fmt.Printf("%d: [%c] [%x]\n", i, str[i], str[i])
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    输出如下:

    range 遍历:
    0: 'G' [47]
    1: 'o' [6f]
    2: ' ' [20]
    3: '爱' [e7 88 b1]
    6: '好' [e5 a5 bd]
    9: '者' [e8 80 85]
    for 遍历:
    0: [G] [47]
    1: [o] [6f]
    2: [ ] [20]
    3: [ç] [e7]
    4: [ˆ] [88]
    5: [±] [b1]
    6: [å] [e5]
    7: [¥] [a5]
    8: [½] [bd]
    9: [è] [e8]
    10: [] [80]
    11: [
    ] [85]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    由此可以看出,通过 range 方式的遍历,是以 rune 为单位,但是相邻字符的索引值并不一定是连续的;通过 for 方式的遍历,是以 byte 为单位。

    1.4. 类型转换

    字符串是不能直接修改的,如果需要修改,需要转换为可变类型 ([]rune[]bype), 待修改完后再转换回来。但不管如何转换,都需要重新分配内存,并复制数据。

    func main() {
    	str := "hello, world!"
    	bs := []byte(str)  // string 转 byte
    	str2 := string(bs) // byte 转 string
    	rs := []rune(str)  // string 转 rune
    	str3 := string(rs) // rune 转 string
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    前面已经讲解 stringrunebyte 的区别和联系,这里再理解他们的转换,是不是就轻松很多了呢。

    1.5. 总结

    Go 语言的代码是由 Unicode 字符组成的,它们都必须由 Unicode 编码规范中的 UTF-8 编码格式进行编码并存储,Unicode 编码规范中的编码格式定义的是:字符与字节序列之间的转换方式。其中的 UTF-8 是一种可变宽的编码方案,它会用一个或多个字节的二进制数来表示某个字符,最多使用四个字节。Go 语言中的一个 string 类型值会由若干个 Unicode 字符组成,每个 Unicode 字符都可以由一个 rune 类型的值来承载。这些字符在底层都会被转换为 UTF-8 编码值,而这些 UTF-8 编码值又会以字节序列的形式表达和存储。因此,一个 string 类型的值在底层就是一个能够表达若干个 UTF-8 编码值的字节序列。对于通过 for range 方式遍历字符串,会先把被遍历的字符串值拆成一个字节序列,然后再试图找出这个字节序列中包含的每一个 UTF-8 编码值,或者说每一个 Unicode 字符。相邻的 Unicode 字符的索引值并不一定是连续的,这取决于前一个 Unicode 字符是否为单字节字符,一旦我们清楚了这些内在机制就不会再困惑了。对于 Go 语言来说,Unicode 编码规范和 UTF-8 编码格式算是基础之一,我们应该了解到它们对 Go 语言的重要性,这对于正确理解 Go 语言中的相关数据类型以及日后的相关程序编写都会很有好处。

    1.6. String Concatenation (字符串连接)

    1.6.1. Using the + operator

    package main
    
    import (
        "fmt"
    )
    
    func main() {
        s1 := "Go"
        s2 := "Programming"
        s3 := "Language"
    
        s := s1 + s2 + s3
        fmt.Println(s)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    $ go run concatenate.go
    
    GoProgrammingLanguage
    
    • 1
    • 2
    • 3

    1.6.2. Using the += operator

    p := "Story"
    p += "Book"
    fmt.Println(p)
    
    • 1
    • 2
    • 3
    go run concatenate.go
    
    StoryBook
    
    • 1
    • 2
    • 3

    1.6.3. Using the Join method

    q := []string{"meetgor.com", "tags", "golang", "string"}
    r := strings.Join(q, "/")
    fmt.Println(r)
    
    • 1
    • 2
    • 3
    go run concatenate.go
    
    meetgor.com/tags/golang/string
    
    • 1
    • 2
    • 3

    1.6.4. Using Sprintf method

    // Using Sprintf function to format strings
    
    name := "peter"
    domain := "telecom"
    service := "ceo"
    
    email := fmt.Sprintf("%s.%s@%s.com", service, name, domain)
    fmt.Println(email)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    go run concatenate.go
    
    ceo.peter@telecom.com
    
    • 1
    • 2
    • 3

    1.6.5. Using Go string Builder method

    package main
    
    import (
        "fmt"
        "strings"
    )
    
    func main() {
      // Using Builder function
    
      c := []string{"j", "a", "v", "a"}
      var builder strings.Builder
      for _, item := range c {
        builder.WriteString(item)
      }
      fmt.Println("builder = ", builder.String())
      b := []byte{'s', 'c', 'r', 'i', 'p', 't'}
      for _, item := range b {
        builder.WriteByte(item)
      }
      fmt.Println("builder = ", builder.String())
      builder.WriteRune('s')
      fmt.Println("builder = ", builder.String())
      fmt.Println("builder = ", builder)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    go run concatenate.go
    
    builder =  java
    builder =  javascript
    builder =  javascripts
    builder =  {0xc000088dd8 [106 97 118 97 115 99 114 105 112 116 115]}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    1.6.6. Using the Bytes buffer method

    package main
    
    import (
        "fmt"
        "bytes"
    )
    
    func main() {
        // Using bytes buffer method
    
        var buf bytes.Buffer
    
        for i := 0; i < 2; i++ {
            buf.WriteString("ja")
        }
        fmt.Println(buf.String())
    
        buf.WriteByte('r')
    
        fmt.Println(buf.String())
    
        k := []rune{'s', 'c', 'r', 'i', 'p', 't'}
        for _, item := range k {
            buf.WriteRune(item)
        }
        fmt.Println(buf.String())
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    go run concatenate.go
    
    jaja
    jajar
    jajarscript
    {[106 97 106 97 114 115 99 114 105 112 116] 0 0}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    1.7. String Comparison

    1.7.1. Using Comparison operators

    package main
    
    import "fmt"
    
    func main() {
        s1 := "gopher"
        s2 := "Gopher"
        s3 := "gopher"
    
        isEqual := s1 == s2
    
      //"gopher" is not same as "Gopher" and hence `false`
        fmt.Printf("S1 and S2 are Equal? %t \n", isEqual)
        fmt.Println(s1 == s2)
    
      // "gopher" is not equal to "Gopher" and hence `true`
        fmt.Println(s1 != s2)
    
      // "Gopher" comes first lexicographically than "gopher" so return true 
      // G -> 71 in ASCII and g -> 103
        fmt.Println(s2 < s3)
        fmt.Println(s2 <= s3)
    
      // "Gopher" is not greater than "gopher" as `G` comes first in ASCII table
      // So G value is less than g i.e. 71 > 103 which is false
        fmt.Println(s2 > s3)
        fmt.Println(s2 >= s3)
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    go run comparison.go
    
    S1 and S2 are Equal? false 
    false
    true
    true
    true
    false
    false
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    1.7.2. Using Compare method

    package main
    
    import(
      "fmt"
      "strings"
    )
    
    func main() {
        s1 := "gopher"
        s2 := "Gopher"
        s3 := "gopher"
    
        fmt.Println(strings.Compare(s1, s2))
        fmt.Println(strings.Compare(s1, s3))
        fmt.Println(strings.Compare(s2, s3))
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    go run comparison.go
    
    1
    0
    -1
    
    • 1
    • 2
    • 3
    • 4
    • 5

    1.7.3. Using strings EqualFold

    package main
    
    import(
      "fmt"
      "strings"
    )
    
    func main() {
    
        s1 := "gopher"
        s2 := "Gopher"
        s3 := "gophy"
    
        fmt.Println(strings.EqualFold(s1, s2))
        fmt.Println(strings.EqualFold(s1, s3))
        fmt.Println(strings.EqualFold(s2, s3))
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    go run comparison.go
    
    true
    false
    false
    
    • 1
    • 2
    • 3
    • 4
    • 5

    1.8. String Manipulation and utility methods

    1.8.1. ToLower, ToUpper and Title functions

    package main
    
    import (
        "fmt"
        "strings"
    
        "golang.org/x/text/cases"
        "golang.org/x/text/language"
    )
    
    func main() {
        s1 := "Ubuntu 22"
        s2 := "meet"
        s3 := "IND"
        fmt.Println(strings.ToLower(s1))
        fmt.Println(strings.ToLower(s2))
        fmt.Println(strings.ToLower(s3))
    
        fmt.Printf("\n")
        fmt.Println(strings.ToUpper(s1))
        fmt.Println(strings.ToUpper(s2))
        fmt.Println(strings.ToUpper(s3))
    
        fmt.Printf("\n")
        cases := cases.Title(language.English)
        fmt.Println(cases.String(s1))
        fmt.Println(cases.String(s2))
        fmt.Println(cases.String(s3))
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    # 100-days-of-golang/scripts/strings
    
    go mod init
    go get golang.org/x/text/cases
    go get golang.org/x/text/language
    
    go run utility.go                                                                                             
    ubuntu 22
    meet
    ind
    
    UBUNTU 22
    MEET
    IND
    
    Ubuntu 22
    Meet
    Ind
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    1.8.2. Contains and ContainsAny functions

    package main
    
    import (
        "fmt"
        "strings"
    )
    
    func main() {
        str := "javascript"
        substr := "script"
        s := "python"
    
        fmt.Println(strings.Contains(str, substr))
        fmt.Println(strings.Contains(str, s))
    
        fmt.Println(strings.ContainsAny(str, "joke"))
        fmt.Println(strings.ContainsAny(str, "xyz"))
        fmt.Println(strings.ContainsAny(str, ""))
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    $ go run main.go
    
    true
    false
    true
    false
    false
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    1.8.3. Split and SplitAfter functions

    package main
    
    import (
        "fmt"
        "strings"
    )
    
    func main() {
        // Split method for splitting string into slice of string
        link := "meetgor.com/blog/golang/strings"
        fmt.Println(strings.Split(link, "/"))
        fmt.Println(strings.SplitAfter(link, "/"))
    
        // SplitAfter method for splitting string into slice of string with the pattern
        data := "200kms50kms120kms"
        fmt.Println(strings.Split(data, "kms"))
        fmt.Println(strings.SplitAfter(data, "kms"))
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    go run utility.go
    
    [meetgor.com blog golang strings]
    [meetgor.com/ blog/ golang/ strings]
    [200 50 120 ]
    [200kms 50kms 120kms ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    1.8.4. Repeat and Fields functions

    package main
    
    import (
        "fmt"
        "strings"
    )
    
    func main() {
        // Repeat method for creating strings with given string and integer
        pattern := "OK"
        fmt.Println(strings.Repeat(pattern, 3))
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    go run utility.go
    
    OKOKOK
    
    • 1
    • 2
    • 3
    package main
    
    import (
        "fmt"
        "strings"
    )
    
    func main() {
        // Fields method for extracting string from the given string with white space as delimiters
        text := "Python is a prgramming language.   Go is not"
        text_data := strings.Fields(text)
        fmt.Println(text_data)
        for _, d := range text_data {
            fmt.Println("data = ", d)
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    go run utility.go
    
    [Python is a prgramming language. Go is not]
    data =  Python
    data =  is
    data =  a
    data =  prgramming
    data =  language.
    data =  Go
    data =  is
    data =  not
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
  • 相关阅读:
    【WINDOWS / DOS 批处理】if命令参数详解(二)
    我要写整个中文互联网界最牛逼的JVM系列教程 | 「JVM与Java体系架构」章节:JVM的位置
    英伟达禁售?FlashAttention助力LLM推理速度提8倍
    【00】FISCO BCOS区块链简介
    Java编程技巧:文件上传、下载、预览
    Windows+Pycharm 如何创建虚拟环境
    #php的pecl工具#
    博客更新计划的说明
    游戏中的随机——“动态平衡概率”算法
    计算机毕业设计ssm+vue基本微信小程序的蛋糕预订平台系统
  • 原文地址:https://blog.csdn.net/wan212000/article/details/132971934