不可变字符串和指针地址
Immutable string and pointer address
在 Go 中 spec 写成:
Strings are immutable: once created, it is impossible to change the
contents of a string.
我有以下代码:
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
我原以为 &str
地址会在 *ptr = "world"
之后更改。就像 Java 一样,我们重新分配字符串引用。
这里的'immutability'是什么?
string
值 是不可变的。
str
不是 string
值。这是一个 变量 (string
类型)。并且变量的值可能会更改,这是您对任何编程语言的期望。
"hello"
是一个 string
值,这是不可变的。 "world"
是另一个 string
值,当您将 "world"
分配给 str
时,您只是将另一个不同的值分配给 str
变量。无论您是直接对 str
执行此操作还是通过指针执行此操作都没有关系。您只是在更改 str
.
表示的变量的值
不可变意味着您不能采用 string
值 "world"
,并更改其第二个字符。例如,如果您有一个接收 string
参数的函数,无论它接收到什么(例如 "hello"
),您都可以确保它始终保持不变。无论何时/如何打印此 string
值,它始终是 "hello"
.
A string
值是引擎盖下的结构值,由 reflect.StringHeader
类型表示:
type StringHeader struct {
Data uintptr
Len int
}
它基本上存储了一个数据指针(指向保存文本的 UTF-8 编码值的字节数组)和 string
值的字节长度。数据数组及其长度不会向您公开,因此您无法修改它们。这是确保 string
值不可变的要素之一。另一个要素是,尽管 string
值可以被索引(索引其字节),但您不能为索引表达式分配新值。例如。使用值"abc"[0]
是有效的,但是给它赋一个新值是无效的,比如"abc"[0] = 'x'
。同样,您不能获取索引 string
值的索引表达式的地址(否则您可以修改指向的值,从而间接修改 string
值)。
这就是 language spec guarantees. Note that there are certain ways to still change string
values, e.g. using package unsafe
的内容,但这不在规范的保证范围内:
Package unsafe contains operations that step around the type safety of Go programs.
Packages that import unsafe may be non-portable and are not protected by the Go 1 compatibility guidelines.
在您导入包 unsafe
的“那一刻”,您将失去语言规范提供的任何保证和安全,从那时起您就不能抱怨任何事情了。但是如果不使用这些“特殊”手段,string
值就不会发生改变。
阅读博客 post Strings, bytes, runes and characters in Go 了解 string
如何在 Go 中实现和工作。
查看相关问题:
What are the possible consequences of using unsafe conversion from []byte to string in go?
在 Go 中 spec 写成:
Strings are immutable: once created, it is impossible to change the contents of a string.
我有以下代码:
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
我原以为 &str
地址会在 *ptr = "world"
之后更改。就像 Java 一样,我们重新分配字符串引用。
这里的'immutability'是什么?
string
值 是不可变的。
str
不是 string
值。这是一个 变量 (string
类型)。并且变量的值可能会更改,这是您对任何编程语言的期望。
"hello"
是一个 string
值,这是不可变的。 "world"
是另一个 string
值,当您将 "world"
分配给 str
时,您只是将另一个不同的值分配给 str
变量。无论您是直接对 str
执行此操作还是通过指针执行此操作都没有关系。您只是在更改 str
.
不可变意味着您不能采用 string
值 "world"
,并更改其第二个字符。例如,如果您有一个接收 string
参数的函数,无论它接收到什么(例如 "hello"
),您都可以确保它始终保持不变。无论何时/如何打印此 string
值,它始终是 "hello"
.
A string
值是引擎盖下的结构值,由 reflect.StringHeader
类型表示:
type StringHeader struct {
Data uintptr
Len int
}
它基本上存储了一个数据指针(指向保存文本的 UTF-8 编码值的字节数组)和 string
值的字节长度。数据数组及其长度不会向您公开,因此您无法修改它们。这是确保 string
值不可变的要素之一。另一个要素是,尽管 string
值可以被索引(索引其字节),但您不能为索引表达式分配新值。例如。使用值"abc"[0]
是有效的,但是给它赋一个新值是无效的,比如"abc"[0] = 'x'
。同样,您不能获取索引 string
值的索引表达式的地址(否则您可以修改指向的值,从而间接修改 string
值)。
这就是 language spec guarantees. Note that there are certain ways to still change string
values, e.g. using package unsafe
的内容,但这不在规范的保证范围内:
Package unsafe contains operations that step around the type safety of Go programs.
Packages that import unsafe may be non-portable and are not protected by the Go 1 compatibility guidelines.
在您导入包 unsafe
的“那一刻”,您将失去语言规范提供的任何保证和安全,从那时起您就不能抱怨任何事情了。但是如果不使用这些“特殊”手段,string
值就不会发生改变。
阅读博客 post Strings, bytes, runes and characters in Go 了解 string
如何在 Go 中实现和工作。
查看相关问题:
What are the possible consequences of using unsafe conversion from []byte to string in go?