源代码中 src/builtin/builtin.go
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
❝
❞
源码包中 src/runtime/string.go:stringStruct 定义的 string 的数据结构如下:
type stringStruct struct {
str unsafe.Pointer
len int
}
发现 string 的数据结构有点类似于切片,切片比它多了一个容量成员。string 和 byte 切片经常互转。
字符串的构建是先构建 stringStruct,再转换成 string:
//go:nosplit
func gostringnocopy(str *byte) string {
ss := stringStruct{str: unsafe.Pointer(str), len: findnull(str)} // 先构造 stringStruct
s := *(*string)(unsafe.Pointer(&ss)) // stringStruct 转换成 string
return s
}
示例:
func ByteToString(s []byte) string {
return string(s)
}
注意这里的转换进行一次内存拷贝:
示例:
func StringToByte(str string) []byte {
return []byte(str)
}
注意这里的转换也会进行一次内存拷贝:
示例:
str := "str1" + "str2" + "str3" + "str4"
rawstring()源代码如下:
// rawstring allocates storage for a new string. The returned
// string and byte slice both refer to the same storage.
// The storage is not zeroed. Callers should use
// b to set the string contents and then drop b.
func rawstring(size int) (s string, b []byte) {
p := mallocgc(uintptr(size), nil, false)
stringStructOf(&s).str = p
stringStructOf(&s).len = size
*(*slice)(unsafe.Pointer(&b)) = slice{p, size, size}
return
}
在 Go 中,string 不包含内存空间,它只有一个内存指针,所以 string 非常轻量,很方便进行传递且不用担心内存拷贝。string 通常指向字符串字面量,字面量存储的位置是只读段,并不是堆或栈上,所以 string 不能被修改。
有时只是临时需要字符串的场景下,byte切片转换成 string 时并不会拷贝内存,而是直接返回一个 string,这个 string 的指针指向切片的内存。
如:
m[string(b)]
来查找map(map是string为key,临时把切片 b 转成string)[]byte 和 string 都可以表示字符串,它们数据结构不同,其衍生出来的方法也不同。
string 擅长的场景:
[]byte擅长的场景:
有什么问题,可以公众号内回复或加我微信交流。