我最近在阅读go的源代码,看到源代码中有一个名为string.go
的文件,但同时,字符串是预先声明的标识符,而且它也被直接用在源代码中?
我发现一些文章说string
是引用类型。但我尝试运行以下代码:
func TestString(t *testing.T) {
s := "abc"
fmt.Println("address of s: ", &s)
xx := func(sss string) {
fmt.Println("address of sss: ", &sss)
sss = "123"
}
xx(s)
fmt.Println("value of s after sss modified the content: ", s)
}
output:
=== RUN TestString
address of s: 0xc00010a560
address of sss: 0xc00010a570
value of s after sss modified the content: abc
--- PASS: TestString (0.00s)
如果string
是引用,那么当我把s
传递给func(sss string)
时,sss
的地址应该和s
相同,并且s
应该被修改,但是它没有被修改,为什么?
Go语言是不是做了一些字符串的事情,让它看起来像一个值类型?但是代码在哪里?如果string
是一个引用类型,而string
的实际类型是type stringStruct
,它应该在某个地方定义行为?
我真的很困惑
1条答案
按热度按时间i7uq4tfw1#
&s
和&sss
是变量的地址,因为它们是两个不同的非零大小的变量,所以它们的地址必须不同,这是您所经历的。Go语言中没有经典C语言意义上的引用类型,
string
是一个类似于结构体的小值,用reflect.StringHeader
来描述:它包含一个存储字符串的UTF-8编码字节的指针和一个字节长度。
当你给
string
类型的变量赋值时,你改变了变量的值(上面的小StringHeader
结构体),但没有改变指向的数据;当你给sss
变量赋值时,原来的s
变量没有改变,它仍然包含指向相同字节的相同数据指针。读取The Go Blog: Strings, bytes, runes and characters in Go
参见相关问题:
不可变字符串和指针地址
Go语言中的string和[] byte有什么区别?