英文:
Is string a reference type or a value type
问题
我最近在阅读Go的源代码。我看到源代码中有一个名为string.go
的文件,但同时,string
也是预声明的标识符,并且在源代码中直接使用了它。
我找到一些文章说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)
}
输出结果为:
=== 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
,那么应该在某个地方定义了它的行为。
这真的让我困惑不已。
英文:
I was recently reading the source code of go. I see that there is a file called string.go
in the source code, but at the same time, the string is the predeclared identifiers, and it also being used in the source code directly?
I found some article that said string
is the reference type. but I try to run the following code:
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)
if the string
is reference, So when I pass the s
to func(sss string)
, the address of sss
should be the same with s
, and s
should be modified, but it wasn't, why?
Is the go did something of string, let it seems like a value type? but where is the code? if the string
is a refernce type and the actual type of string
is type stringStruct
, it should be defined the behavior somewhere?
It really confuse me
答案1
得分: 3
&s
和&sss
是变量的地址。由于它们是两个不同的非零大小变量,它们的地址必须不同,这就是你所经历的情况。
在Go语言中,没有经典C语言意义上的引用类型。string
是一个类似结构体的小值,由reflect.StringHeader
描述:
type StringHeader struct {
Data uintptr
Len int
}
它包含一个指针,指向存储字符串的UTF-8编码字节的位置,以及一个字节长度。
当你将某个值赋给string
类型的变量时,你改变的是变量的值(上述小的StringHeader
结构体),而不是指向的数据。当你将某个值赋给sss
变量时,原始的s
变量不会改变,它仍然包含指向相同字节的相同数据指针。
阅读The Go Blog: Strings, bytes, runes and characters in Go
参考相关问题:
https://stackoverflow.com/questions/47352449/immutable-string-and-pointer-address/47352588#47352588
英文:
&s
and &sss
are the addresses of variables. Since they are 2 distinct non-zero size variables, their addresses must be different, which you experience.
There are no reference types in Go in the classic C sense. A string
is a small struct-like value described by reflect.StringHeader
:
type StringHeader struct {
Data uintptr
Len int
}
It contains a pointer where the UTF-8 encoded bytes of the string are stored, and a byte-length.
When you assign something to a variable of string
type, you change the value of the variable (the above small StringHeader
struct), but not the pointed data. When you assign something to the sss
variable, the original s
variable is unchanged, it still contains the same data pointer pointing to the same bytes.
Read The Go Blog: Strings, bytes, runes and characters in Go
See related questions:
https://stackoverflow.com/questions/47352449/immutable-string-and-pointer-address/47352588#47352588
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论