go 字符串

2023-11-12 08:12:20 浏览数 (1)

修改字符串

要修改字符串,需要先将其转换成[]rune或[]byte,完成后再转换为string。无论哪种转换,都会重新分配内存,并复制字节数组。

代码语言:go复制
func changeString() {

        s1 := "hello"

        // 强制类型转换

        byteS1 := []byte(s1)

        byteS1[0] = 'H'

        fmt.Println(string(byteS1))

        s2 := "博客"

        runeS2 := []rune(s2)

        runeS2[0] = '狗'

        fmt.Println(string(runeS2))

    }
  1. 先将这段内存拷贝到堆或者栈上;
  2. 将变量的类型转换成 []byte 后并修改字节数据;
  3. 将修改后的字节数组转换回 string
代码语言:go复制
// string is the set of all strings of 8-bit bytes, conventionally but not

// necessarily representing UTF-8-encoded text. A string may be empty, but

// not nil. Values of string type are immutable.

type string string

string是8位字节的集合,通常但不一定代表UTF-8编码的文本。string可以为空,但不能为nil。**string的值是不能改变的**

Go源代码为 UTF-8 编码格式的,源代码中的字符串直接量是 UTF-8 文本。所以Go语言中字符串是UTF-8编码格式的。

代码语言:go复制
// rune is an alias for int32 and is equivalent to int32 in all ways. It is

// used, by convention, to distinguish character values from integer values.

type rune = int32

rune是int32的别名,在所有方面都等同于int32,按照约定,它用于区分字符值和整数值。

rune一个值代表的就是一个Unicode字符,因为一个Go语言中字符串编码为UTF-8,使用1-4字节就可以表示一个字符,所以使用int32类型范围可以完美适配。

见坑

字符串拼接

优先使用 strings.Builder 而不是 =

子字符串操作及内存泄露

字符串的切分也会跟切片的切分一样,可能会造成内存泄露。例子:有一个handleLog的函数,接收一个string类型的参数log,假设log的前4个字节存储的是log的message类型值,需要从log中提取出message类型,并存储到内存中。下面是相关代码:

代码语言:txt复制
func (s store) handleLog(log string) error {

    if len(log) < 4 {

        return errors.New("log is not correctly formatted")

    }

    message := log[:4]

    s.store(message)

    // Do something

}

使用log:4的方式提取出了message,假设参数log是一个包含成千上万个字符的字符串。当使用log:4操作时,实际上是返回了一个字节切片,该切片的长度是4,而容量则是log字符串的整体长度。那么实际上存储的message不是包含4个字节的空间,而是整个log字符串长度的空间。所以就有可能会造成内存泄露。如下图所示:

那怎么避免呢?使用拷贝。将uuid提取后拷贝到一个字节切片中,这时该字节切片的长度和容量都是4。如下:

代码语言:go复制
func (s store) handleLog(log string) error {

  if len(log) < 4 {

    return errors.New("log is not correctly formatted")

  }

  

  message := string([]byte(log[:4])) 

  s.store(message)

  // Do something

}

字符串的长度

内建的 len()函数返回byte的数量,而不是像Python中计算好的unicode字符串中字符的数量。

要在Go中得到相同的结果,可以使用“unicode/utf8”包中的 RuneCountInString()函数。

代码语言:go复制
package main



import("fmt""unicode/utf8")



func main(){  

    data :="♥"

    fmt.Println(utf8.RuneCountInString(data))//prints: 1}

理论上说 RuneCountInString()函数并不返回字符的数量,因为单个字符可能占用多个rune。

我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!

0 人点赞