是否有人能够解释为什么&c1.name
的地址在功能changeMe()
中被更改后是相同的。我认为Go中的字符串是不可变的。
package main
import "fmt"
type customer struct {
name string
age int
}
func main() {
c1 := customer{"Todd", 44}
fmt.Println(&c1.name) // 0x8201e4120
changeMe(&c1)
fmt.Println(c1) // {Rocky 44}
fmt.Println(&c1.name) // 0x8201e4120
}
func changeMe(z *customer) {
fmt.Println(z) // &{Todd 44}
fmt.Println(&z.name) // 0x8201e4120
z.name = "Rocky"
fmt.Println(z) // &{Rocky 44}
fmt.Println(&z.name) // 0x8201e4120
}
答案 0 :(得分:9)
字符串的不变性与变量的不变性不同。
字符串的不变性意味着字符串中的字符无法更改。这适用于Go。 Go在切割字符串时会使用它,如下例所示。
Go中的变量总是可变的。更改字符串变量时,将更改变量的内部字段(指针和长度)。变量的地址永远不会改变。
下面的示例介绍了Go字符串变量的内部结构。第一个整数是字符数组的地址,第二个是长度。
请参阅Go http://research.swtch.com/godata中有关字符串内部的文章。
package main
import (
"fmt"
"reflect"
"unsafe"
)
func main() {
var x string = "abc"
fmt.Println(x, &x, (*reflect.StringHeader)(unsafe.Pointer(&x)))
x = "cde"
fmt.Println(x, &x, (*reflect.StringHeader)(unsafe.Pointer(&x)))
x = x[1:]
fmt.Println(x, &x, (*reflect.StringHeader)(unsafe.Pointer(&x)))
}