2016-04-19 25 views
1

kann mir jemand erklären, warum die Adresse &c1.name dieselbe ist, nachdem sie in der Funktion changeMe() geändert wurde. Ich dachte, dass Strings in Go unveränderlich sind.Unveränderliche Zeichenfolgen 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 
} 
+0

weil 'c1' ist ein einzigartiges Beispiel, und seine Adresse wird nicht geändert werden, können Sie nur seinen Wert ändern –

+0

ja,' c1' nicht geändert werden, aber es ist Feld 'Name 'ist unveränderlich, oder? Wenn ich den Namen ändere, sollte er eine neue Adresse haben. Was Wenn ich eine extrem große Zeichenfolge speichern möchte, wie speichert der Compiler sie, wenn sie immer noch dieselbe Adresse verwendet? – camabeh

Antwort

9

Die Unveränderlichkeit von Strings ist nicht dasselbe wie Unveränderlichkeit von Variablen.

Die Unveränderlichkeit von Zeichenfolgen bedeutet, dass die Zeichen in der Zeichenfolge nicht geändert werden können. Dies gilt für Go. Go verwendet es beim Schneiden von Strings, wie im folgenden Beispiel gezeigt.

Variablen in Go sind immer änderbar. Wenn eine String-Variable geändert wird, werden die internen Felder der Variablen (Zeiger und Länge) geändert. Die Adresse der Variablen ändert sich nie.

Das folgende Beispiel zeigt die Interna der Variablen Go String. Die erste Ganzzahl ist eine Adresse für das Array von Zeichen und die zweite ist die Länge.

Siehe den Artikel über Interna von String in 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))) 
} 

Playground

+2

Es gibt auch den [StringHeader] (https://golang.org/pkg/reflect/#StringHeader) im Paket reflect, das das Layout der tatsächlichen Zeichenfolgenstruktur in [runtime/string.go] (https: // golang) widerspiegelt .org/src/Laufzeit/string.go # L215) – JimB

+0

Danke. Es macht jetzt alles Sinn. – camabeh

Verwandte Themen