Go中的不可变字符串

huangapple go评论72阅读模式
英文:

Immutable strings in Go

问题

有人能解释一下为什么在函数changeMe()中修改后,&c1.name的地址仍然相同吗?我以为在Go语言中字符串是不可变的。

package main

import "fmt"

type customer struct {
	name string
	age  int
}

func main() {
	c1 := customer{"Todd", 44}
	fmt.Println(&c1.name) // 0x8201e4120

	changeMe(&c1)

	fmt.Println(c1)       // {Rocky 44}
	fmt.Println(&c1.name) // 0x8201e4120
}

func changeMe(z *customer) {
	fmt.Println(z)       // &{Todd 44}
	fmt.Println(&z.name) // 0x8201e4120
	z.name = "Rocky"
	fmt.Println(z)       // &{Rocky 44}
	fmt.Println(&z.name) // 0x8201e4120
}
英文:

is anyone able to explain me why the address of &c1.name is the same after being changed in function changeMe(). I thought strings are immutable in Go.

package main

import "fmt"

type customer struct {
	name string
	age  int
}

func main() {
	c1 := customer{"Todd", 44}
	fmt.Println(&c1.name) // 0x8201e4120

	changeMe(&c1)

	fmt.Println(c1)       // {Rocky 44}
	fmt.Println(&c1.name) // 0x8201e4120
}

func changeMe(z *customer) {
	fmt.Println(z)       // &{Todd 44}
	fmt.Println(&z.name) // 0x8201e4120
	z.name = "Rocky"
	fmt.Println(z)       // &{Rocky 44}
	fmt.Println(&z.name) // 0x8201e4120
}

答案1

得分: 17

字符串的不可变性与变量的不可变性不同。

字符串的不可变性意味着字符串中的字符不能被改变。这在Go语言中是成立的。Go语言在切片字符串时使用了这一特性,如下面的示例所示。

Go语言中的变量始终是可变的。当一个字符串变量被改变时,变量的内部字段(指针和长度)会被改变,但变量的地址不会改变。

下面的示例展示了Go语言字符串变量的内部结构。第一个整数是字符数组的地址,第二个整数是长度。

请参阅关于Go语言字符串内部结构的文章http://research.swtch.com/godata

package main

import (
        "fmt"
        "reflect"
        "unsafe"
)

func main() {
    var x string = "abc"
    fmt.Println(x, &x, (*reflect.StringHeader)(unsafe.Pointer(&x)))
    x = "cde"
    fmt.Println(x, &x, (*reflect.StringHeader)(unsafe.Pointer(&x)))
    x = x[1:]
    fmt.Println(x, &x, (*reflect.StringHeader)(unsafe.Pointer(&x)))
}

<kbd>Playground</kbd>

英文:

The immutability of strings is not the same as immutability of variables.

Immutability of strings means that the characters in the string cannot be changed. This holds true for Go. Go makes use of it when slicing strings as shown in the example below.

Variables in Go are always mutable. When a string variable is changed, the internal fields of the variable (pointer and length) are changed. The address of variable never changes.

The example below presents the internals of Go string variable. The first integer is an address to the array of characters and the second is the length.

See the article on internals of string in Go http://research.swtch.com/godata.

package main

import (
        &quot;fmt&quot;
        &quot;reflect&quot;
        &quot;unsafe&quot;
)

func main() {
    var x string = &quot;abc&quot;
	fmt.Println(x, &amp;x, (*reflect.StringHeader)(unsafe.Pointer(&amp;x)))
    x = &quot;cde&quot;
    fmt.Println(x, &amp;x, (*reflect.StringHeader)(unsafe.Pointer(&amp;x)))
    x = x[1:]
    fmt.Println(x, &amp;x, (*reflect.StringHeader)(unsafe.Pointer(&amp;x)))
}

<kbd>Playground</kbd>

huangapple
  • 本文由 发表于 2016年4月19日 22:02:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/36720693.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定