在Go 规范中写道:
字符串是不可变的:一旦创建,就不可能改变字符串的内容.
我有以下代码:
str := "hello"
fmt.Printf("%p\n",&str) // 0x1040c128
fmt.Printf("%v\n",str) // hello
ptr := &str
*ptr = "world"
fmt.Printf("%p\n",&str) // 0x1040c128
fmt.Printf("%v\n",str) // world
Run Code Online (Sandbox Code Playgroud)
我&str原本预计地址会改变*ptr = "world".正如Java所发生的那样,我们重新分配字符串引用.
什么是"不变性"?
为了测试目的,我试图从库中模拟Rows.Scan方法database/sql。签名如下所示:
func (r *Rows) Scan(dest ...interface{}) error
Run Code Online (Sandbox Code Playgroud)
如何使用此功能的许多示例表明,您将指向字符串的指针(例如)传递给Scan方法,它将通过该指针分配值。
var name string
rows.Scan(&name)
Run Code Online (Sandbox Code Playgroud)
我一直在尝试为自己的理解并最终为了嘲笑而重新创建类似的东西,但是它不起作用。
func MockScan(args ...interface{}) {
var s2 string
fmt.Println(args[0])
args[0] = &s2
fmt.Println(args[0])
}
func main() {
var s1 string
fmt.Println(&s1)
MockScan(&s1)
fmt.Println(&s1)
}
Run Code Online (Sandbox Code Playgroud)
结果是:
0xc000012950
0xc000012950
0xc000012960
0xc000012950
Run Code Online (Sandbox Code Playgroud)
我的初始字符串从不采用新值的地方。我知道字符串是不可变的(尽管我对这个概念的真正理解有点动摇),但是实际Rows.Scan方法却设法改变了字符串。