2016-04-28 2 views
2

Nachdem ich alle Elemente aus einem Slice (src) in ein neues Slice (dst) kopiert haben, zeigen alle Elemente in dst auf das letzte Element von src.Nach einem Golang Range kopieren alle Elemente auf das letzte Element des src Slice

package main 

import (
    "fmt" 
) 

func main() { 
    src := []string{"a", "b", "c"} 
    dst := []*string{} 
    for _, val := range src { 
     dst = append(dst, &val) 
    } 

    for i, s := range dst { 
     fmt.Printf("%v - %v\n", i, *s) 
    } 
} 

>>> 0 - c 
>>> 1 - c 
>>> 2 - c 

Warum werden "a" und "b" nicht in den dst slice kopiert?

+0

Ich werde es nicht als Duplikat markieren, da Sie bereits ein paar gute Antworten bekommen, aber sehen: https://golang.org/ doc/faq # closures_and_goroutines – JimB

Antwort

6

Die Lösung ist einfach, aber kontra intuitiv in Bezug auf das, was Sie von der range Aussage erwarten würden.

Die Variable val wird nur einmal instanziiert und enthält in jeder Iteration den Wert von src[i]. Es hat nicht den tatsächlichen Zeiger auf src[i]. Stattdessen wird der Wert src[i] in den Speicher kopiert, der val zugewiesen ist. Mit dem Zeiger von val erhalten Sie genau das, und nicht den Zeiger auf src[i].

package main 

import (
    "fmt" 
) 

func main() { 
    src := []string{"a", "b", "c"} 
    dst := []*string{} 
    for _, val := range src { 
     dst = append(dst, &val) 
    } 

    for i, s := range dst { 
     fmt.Printf("%v - %v - %p\n", i, *s, s) 
    } 

    //modify only contents of first index 
    *dst[0] = "hi val" 

    for i, s := range dst { 
     fmt.Printf("%v - %v - %p\n", i, *s, s) 
    } 
} 

>>>> 
0 - c - 0x1040a120 
1 - c - 0x1040a120 
2 - c - 0x1040a120 
0 - hi val - 0x1040a120 
1 - hi val - 0x1040a120 
2 - hi val - 0x1040a120 

Während im Nachhinein liegt auf der Hand - for _, val ->: = < - range src - es kann, kann man in den Arsch beißen, wenn Sie dessen nicht bewusst sind, so deshalb diese Warnung.

PS. Dies gilt auch für src als Karte.

4

Hinzufügen zu @ RickyA's Antwort.

Um das zu erreichen, was Sie Sie versuchen, zu tun tun müssen:

for i := range src { 
    dst[i] = &src[i] 
} 
Verwandte Themen