修改字符串
要修改字符串,需要先将其转换成[]rune或[]byte
,完成后再转换为string
。无论哪种转换,都会重新分配内存,并复制字节数组。
func changeString() {
s1 := "hello"
// 强制类型转换
byteS1 := []byte(s1)
byteS1[0] = 'H'
fmt.Println(string(byteS1))
s2 := "博客"
runeS2 := []rune(s2)
runeS2[0] = '狗'
fmt.Println(string(runeS2))
}
- 先将这段内存拷贝到堆或者栈上;
- 将变量的类型转换成
[]byte
后并修改字节数据; - 将修改后的字节数组转换回
string
;
// 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腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!