Immutable string and pointer address

穿精又带淫゛_ 提交于 2020-01-20 06:26:05

问题


In Go spec is written:

Strings are immutable: once created, it is impossible to change the contents of a string.

I have following code:

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  

I would have expected &str address was changed after *ptr = "world". As it would happen with Java, where we reassign String references.

What is 'immutability' here?


回答1:


string values are immutable.

str is not a string value. It's a variable (of string type). And values of variables may be changed, that's what you'd expect from any programming language.

"hello" is a string value, and this is what is immutable. "world" is another string value, and when you assign "world" to str, you just assign another, different value to the str variable. It doesn't matter if you're doing it directly to str, or via a pointer. You're just changing the value of the variable denoted by str.

Immutable means you cannot take the string value "world", and change its second character for example. If you have a function for example which receives a string argument, whatever it receives (e.g. "hello"), you can be sure it will always remain the same. No matter when / how you print this string value, it will always be "hello".

A string value is a struct value under the hood, represented by the reflect.StringHeader type:

type StringHeader struct {
    Data uintptr
    Len  int
}

It basically stores a data pointer (to the byte array holding the UTF-8 encoded value of the text), and the byte-length of the string value. The data array and its length are not exposed to you, so you can't modify them. This is one element of making sure that string values are immutable. Another element is that although string values can be indexed (which indexes its bytes), you can not assign new values to the index expressions. E.g. it is valid to use the value "abc"[0], but it is invalid to assign a new value to it like "abc"[0] = 'x'. Similarly, you cannot take the address of an index expression indexing a string value (else you could modify the pointed value and thus indirectly the string value).

This is what the language spec guarantees. Note that there are certain ways to still change string values, e.g. using package unsafe, but this falls outside the guarantees of the spec:

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.

The "moment" you import package unsafe, you'll lose any guarantees and safety provided by the language spec, and from there on you can't complain for anything. But without using these "special" means, it cannot happen that a string value gets altered.

Read the blog post Strings, bytes, runes and characters in Go for how string is implemented and works in Go.

See related questions:

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?



来源:https://stackoverflow.com/questions/47352449/immutable-string-and-pointer-address

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!