繁体   English   中英

不可变的字符串和指针地址

[英]Immutable string and pointer address

在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  

我希望&str地址在*ptr = "world"后改变。 正如Java所发生的那样,我们重新分配字符串引用。

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

string 是不可变的。

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

"hello"是一个string值,这是不可变的。 "world"是另一个string值,当您为str分配"world"时,您只需为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'是无效"abc"[0] = 'x' 类似地,您不能将索引表达式的地址索引为string值(否则您可以修改指向的值,从而间接地修改string值)。

这是语言规范保证的。 请注意,仍有某些方法可以更改string值,例如使用package unsafe ,但这不符合规范的保证:

Package unsafe包含围绕Go程序类型安全的操作。

导入不安全的软件包可能是不可移植的,并且不受Go 1兼容性指南的保护。

你导入软件包unsafe的“时刻”,你将失去语言规范提供的任何保证和安全,从那里你不能抱怨什么。 但是, 如果不使用这些“特殊”方法,就不会发生string值被改变的情况。

阅读Go中的字符串,字节,符文和字符的博客文章了解如何实现string并在Go中工作。

查看相关问题:

Go中的字符串和[]字节有什么区别?

go中使用从[] byte到string的不安全转换可能带来的后果是什么?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM