2016-08-13 14 views
5

Zauważyłem dziwne zachowanie z dopiskiem Golanga(). Rozumiem podstawową koncepcję tego, w jaki sposób zdolność segmentacji wpływa na to, czy nowa tablica bazowa zostanie przydzielona, ​​ale dlaczego jest taka, czy używam opcji fmt.Println() PO ZASTOSOWANIU, co miało wpływ na wynik dodania?Dziwne zachowanie z dopiskiem Golang() jest dotknięte przez fmt.Println()

package main 

import "fmt" 

func main() { 
    a := []byte("AAA") 

    b := append(a, []byte("BBB")...) 
    fmt.Println(" a: ", string(a), " b: ", string(b)) 

    c := append(a, []byte("CCC")...) 
    fmt.Println(" a: ", string(a), " b: ", string(b), " c: ", string(c)) 

    fmt.Println(&b) //try commenting this out and in and running the program 
} 

link, aby uruchomić kod tutaj: https://play.golang.org/p/jJ-5ZxTBIn

+1

OP, uprościłem Twój przykład, usuwając nieprzydatny pierwszy przydział. Możesz się wycofać, jeśli się nie zgadzasz. –

+2

To naprawdę wygląda na to, że kompilator błędnie pomyślał, że może coś zoptymalizować, i zachowuje tylko poprawną wartość b, gdy zostanie wydrukowany później. Potwierdziłem, że tak się nie dzieje na przykład z 1.4.2. Powinno to przyciągnąć uwagę golang-nuts, na wypadek, gdyby nie było już błędów. –

+0

Rozumiem, że ten przykład może bardzo Cię zdezorientować. Miłym artykułem jest https://blog.golang.org/go-slices-usage-and-internals. Kawałek jest czymś, co wskazuje na tablicę - pamięta tablicę, gdzie wskazuje, swoją długość i pojemność.Zwykle nie dbamy o pojemność, ale w dołączeniu jest bardzo ważne. Append może współdzielić pamięć z poprzednią, jeśli jest wystarczająco dużo miejsca, ale nie będzie współdzielona, ​​jeśli nie jest. W naszym przypadku umieść * fmt.Println (cap (a)) * po a = [] bajcie. Zwróciło mi 8. Oznacza to, że podczas gdy b i c będą krótsze, wskażą na to samo wspomnienie. – lofcek

Odpowiedz

3

Masz rację: To dlatego The Go Playground wersja jest stary (go1.6.2), użyj nowej wersji.


Prawidłowe wyjściowego (za pomocą go version go1.7rc6) wynosi:

a: AAA b: AAABBB 
a: AAA b: AAACCC c: AAACCC 

1- Go zabaw (go1.6.2)

package main 

import "fmt" 

func main() { 
    a := make([]byte, 100, 1000) 
    a = []byte("AAA") 

    b := append(a, []byte("BBB")...) 
    fmt.Println(" a: ", string(a), " b: ", string(b)) 

    c := append(a, []byte("CCC")...) 
    fmt.Println(" a: ", string(a), " b: ", string(b), " c: ", string(c)) 

    //fmt.Println(&b) //try commenting this out and in and running the program 
} 

Wydajność:

a: AAA b: AAABBB 
a: AAA b: AAABBB c: AAACCC 

2- Go zabaw (go1.6.2)

package main 

import "fmt" 

func main() { 
    a := make([]byte, 100, 1000) 
    a = []byte("AAA") 

    b := append(a, []byte("BBB")...) 
    fmt.Println(" a: ", string(a), " b: ", string(b)) 

    c := append(a, []byte("CCC")...) 
    fmt.Println(" a: ", string(a), " b: ", string(b), " c: ", string(c)) 

    fmt.Println(&b) //try commenting this out and in and running the program 
} 

Wydajność:

a: AAA b: AAABBB 
a: AAA b: AAACCC c: AAACCC 
&[65 65 65 67 67 67] 

pomocą go version go1.7rc6:

package main 

import "fmt" 

func main() { 
    a := make([]byte, 100, 1000) 
    a = []byte("AAA") 

    b := append(a, []byte("BBB")...) 
    fmt.Println(" a: ", string(a), " b: ", string(b)) 

    c := append(a, []byte("CCC")...) 
    fmt.Println(" a: ", string(a), " b: ", string(b), " c: ", string(c)) 

    //fmt.Println(&b) //try commenting this out and in and running the program 
} 

O utput:

a: AAA b: AAABBB 
a: AAA b: AAACCC c: AAACCC 
+0

Dobrze wiedzieć, że to zostało naprawiony! – Salitter

1

będę Podsumowując:

a := make([]byte, 100, 1000) 
a = []byte("AAA") 

tworzy kawałek, w pierwszej linii, ale w drugi tworzy nową tablicę i plasterek ponownie.

Pojemność tej nowej macierzy zależy od wersji kompilatora, dlatego dobry napisany kod nie powinien stanowić żadnego innego założenia, niż będzie wynosił 3 lub więcej.

Zachowaj ostrożność podczas korzystania z Append. Zwrócony kawałek może być płytką lub głęboką kopią poprzedniego wycinka. Który z nich zależy od pojemności macierzy. Jeśli potrzebujesz głębokiej kopii, musisz to zrobić ręcznie.

b:=make([]byte, len(a)) 
copy(b,a) 
+0

To wcale nie odpowiada na pytanie. Problemem był błąd kompilatora. –