2016-08-01 4 views
1

Ich habe eine Instanz einer Struktur, die ein Array-Feld hat. Wenn eine goroutine das Array auf der Instanz ersetzt, haben alle anderen Handles dieser Instanz immer noch das ursprüngliche Array. Warum ist das? Was sollte ich ändern, damit die Instanz Container die Änderung widerspiegelt, die an der Goroutine vorgenommen wurde?String-Array in der Instanz ersetzt wird nicht reflektiert

Ein einfaches Beispiel ist auch hier wider: https://play.golang.org/p/dXVKN6o8aP

func Create() Container { 
    instance := *&Container{ 
     values: []string{"initial value"}, 
    } 
    go func() { 
     instance.values = []string{"modified value"} 
     fmt.Print("values updated") 
    }() 
    return instance 
} 

func main() { 
    instance := Create() 
    time.Sleep(100 * time.Millisecond) 
    fmt.Printf("%[1]v", instance.values) 
    //prints "initial value", but I expected "modified value" 
} 
+1

Es gibt keine "Handles" (Zeiger) zu "Container" - Sie geben die Struktur nach Wert zurück, nicht einen Zeiger darauf. –

Antwort

3

Es ist, weil Sie die Scheibe Wert verwenden. Sie geben den Wert des Schnitts, der zurückgegeben wird, an main per Kopie zurück. Goroutine führt dann den ursprünglichen Wert aus und aktualisiert ihn. Nehmen Sie folgende Änderungen:

func Create() *Container { // return a pointer to container 

    // instance is now initialized and points to a Container value 
    // (i.e. instance is of type *Container) 
    instance := &Container{ 
     values: []string{"initial value"}, 
    } 
    go func() { 
     instance.values = []string{"modified value"} 
     fmt.Print("values updated") 
    }() 
    return instance 
} 

Nun, da Haupt hat einen Zeiger auf die oben instance, Änderungen von goroutine getan sichtbar.

Beispiel: https://play.golang.org/p/AKwUZfTu0s

, auch einen neuen Wert zu erstellen, können Sie direkt den Namen des Typs verwenden:

instance := Container{ // instance is of type Container 
    // ... 
} 

Und zu erstellen und einen Zeiger eines Typs, die Verwendung zu initialisieren:

instance := &Container{ // instance is of type *Container 
    // ... 
} 

etwas zu tun, wie unten ist redundant:

instance := *&Container{ // instance is of type Container. Same as first declaration 
    // ... 
}