Go

2016-04-19 4 views
1

の変更不可能な文字列は、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 
} 
+0

'c1'は一意のインスタンスであり、そのアドレスは、あなただけの値を変更することができ、変更されません –

+0

はい、' c1'が変更されていないが、それは、フィールド '名前だから'不変ですよね?だから私は 'name'を変更するときに新しいアドレスを持つべきです。もし私が極端に大きな文字列を格納したいのであれば、コンパイラは同じアドレスを使用しているときにどのように格納しますか? – camabeh

答えて

9

文字列の不変性は、変数の不変性と同じではありません。

文字列の不変性とは、文字列内の文字を変更できないことを意味します。これはGoに対しても当てはまります。 Goは、以下の例に示すように、文字列をスライスするときに使用します。

Goの変数は常に変更可能です。文字列変数が変更されると、変数の内部フィールド(ポインタと長さ)が変更されます。変数のアドレスは決して変更されません。

以下の例は、Go文字列変数の内部構造を示しています。最初の整数は文字の配列へのアドレスで、2番目の長さは文字の長さです。

文字列の内部についての記事を参照してください。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))) 
} 

Playground

+2

リフレクトパッケージに[StringHeader](https://golang.org/pkg/reflect/#StringHeader)もあります。実際の文字列構造のレイアウトは[runtime/string.go]に反映されています(https:// golang .org/src/runtime/string.go#L215) – JimB

+0

ありがとうございます。今はすべて意味があります。 – camabeh