string - 不可变字符串和指针地址

标签 string go immutability

围棋 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 中发生的那样,我们重新分配 String 引用。

这里的“不变性”是什么?

最佳答案

string values 是不可变的。

str 不是 string 值。它是一个变量(属于string 类型)。变量的值可能会改变,这是您对任何编程语言的期望。

"hello" 是一个 string 值,这是不可变的。 "world" 是另一个 string 值,当你将 "world" 赋给 str 时,你只是赋值另一个, str 变量的不同值。无论您是直接对 str 执行此操作,还是通过指针执行此操作都没有关系。您只是在更改由 str 表示的变量的值。

不可变意味着您不能使用string"world",并更改它的第二个字符。例如,如果您有一个接收 string 参数的函数,无论它接收到什么(例如 "hello"),您都可以确保它始终保持不变。无论何时/如何打印此 string 值,它始终是 "hello"

string 值是引擎盖下的结构值,由 reflect.StringHeader 表示输入:

type StringHeader struct {
    Data uintptr
    Len  int
}

它基本上存储了一个数据指针(指向保存文本的 UTF-8 编码值的字节数组)和 string 值的字节长度。数据数组及其长度不会向您公开,因此您无法修改它们。这是确保 string 值不可变的要素之一。另一个要素是,尽管可以对 string 值进行索引(索引其字节),但您不能为索引表达式分配新值。例如。使用值 "abc"[0] 是有效的,但是给它分配一个新值是无效的,比如 "abc"[0] = 'x' .同样,您不能获取索引 string 值的索引表达式的地址(否则您可以修改指向的值,从而间接修改 string 值)。

这就是language spec保证。请注意,仍有某些方法可以更改 string 值,例如使用包 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 值就不会发生改变。

阅读博文 Strings, bytes, runes and characters in Go了解 string 在 Go 中是如何实现和工作的。

查看相关问题:

What is the difference between the string and []byte in Go?

What are the possible consequences of using unsafe conversion from []byte to string in go?

关于string - 不可变字符串和指针地址,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47352449/

相关文章:

java - 在 Java 中过滤命令行输入中的符号

c# - 子串深度扫描

php - 通过php查找字符串中第一次出现的数字位置

r - 计算数据串中的某些化学 react

opengl - 如何在 MacOS (Lion-10.8) 上的 Go 中创建 OpenGL 3.2 上下文

python - 如何用迭代器修改可迭代对象的元素? IE。如何在 Python 中获取写迭代器?

Julia:非破坏性更新不可变类型变量

linux - 如何检测 Go 中的操作系统版本?

sockets - golang grpc 套接字调整

ios - 尝试附加结构数组时发生突变错误