2013-05-14 5 views
7

Ich versuche, warum der folgende Test-Code zu verstehen, wird nicht wie erwartet funktioniert:Warum bleiben Änderungen an einer Struktur über eine Methode bestehen?

package main 

import (
    "fmt" 
    "strings" 
) 

type Test struct { 
    someStrings []string 
} 

func (this Test) AddString(s string) { 
    this.someStrings = append(this.someStrings, s) 
    this.Count() // will print "1" 
} 

func (this Test) Count() { 
    fmt.Println(len(this.someStrings)) 
} 

func main() { 
    var test Test 
    test.AddString("testing") 
    test.Count() // will print "0" 
} 

Dieser Druck würde:

"1" 
"0" 

Was bedeutet, dass someStrings offenbar geändert wird ... und es ist dann nicht .

Jeder weiß, was könnte das Problem sein?

Antwort

12

Die AddString-Methode verwendet einen Wert (Kopie) -Empfänger. Die Änderung wird an der Kopie vorgenommen, nicht am Original. Ein Zeiger Empfänger muss verwendet werden, um die ursprüngliche Einheit zu mutieren:

package main 

import (
     "fmt" 
) 

type Test struct { 
     someStrings []string 
} 

func (t *Test) AddString(s string) { 
     t.someStrings = append(t.someStrings, s) 
     t.Count() // will print "1" 
} 

func (t Test) Count() { 
     fmt.Println(len(t.someStrings)) 
} 

func main() { 
     var test Test 
     test.AddString("testing") 
     test.Count() // will print "0" 
} 

Playground


Ausgabe

1 
1 
1

Ihre Funktionen für das Objekt definiert sind, sich eher als ein Zeiger auf das Objekt .

func (this Test) AddString(s string) { 
    this.someStrings = append(this.someStrings, s) 
    this.Count() // will print "1" 
} 

Die obige Funktion ist auf den konkreten Daten definiert. Dies bedeutet, dass beim Aufruf der Funktion der Wert this als Kopie der Daten übergeben wird. Daher werden alle Mutationen, die Sie an this vornehmen, auf der Kopie ausgeführt (in diesem Fall ändert die Mutation den Zeiger, auf den 'someStrings' zeigt. Wir können die gleiche Funktion für einen Zeiger von Test wie jnml schreiben:

func (this *Test) AddString(s string) { 
    this.someStrings = append(this.someStrings, s) 
    this.Count() // will print "1" 
} 

Wie Sie sehen können, ist die Funktionsdefinition (this *Test) statt (this Test). das bedeutet, dass die Variable this durch Referenz übergeben wird, und alle Mutationen, die stattfinden, sind auf dem ursprünglichen Objekt durchgeführt Mutationen.

Verwandte Themen