2016-03-07 7 views
5

Wenn eine große Struktur über einen Kanal in Go gesendet wird, wird sie tatsächlich zwischen Gououtines kopiert?Wird eine Struktur zwischen Goroutinen kopiert, wenn sie über einen Golang-Kanal gesendet wird?

Zum Beispiel wird Go in dem folgenden Code tatsächlich alle LargeStruct-Daten zwischen Gououtines Producer und Consumer kopieren?

package main 

import (
    "fmt" 
    "sync" 
) 

type largeStruct struct { 
    buf [10000]int 
} 

func main() { 
    ch := make(chan largeStruct) 
    wg := &sync.WaitGroup{} 
    wg.Add(2) 
    go consumer(wg, ch) 
    go producer(wg, ch) 
    wg.Wait() 
} 

func producer(wg *sync.WaitGroup, output chan<- largeStruct) { 
    defer wg.Done() 
    for i := 0; i < 5; i++ { 
     fmt.Printf("producer: %d\n", i) 
     output <- largeStruct{} 
    } 
    close(output) 
} 

func consumer(wg *sync.WaitGroup, input <-chan largeStruct) { 
    defer wg.Done() 
    i := 0 
LOOP: 
    for { 
     select { 
     case _, ok := <-input: 
      if !ok { 
       break LOOP 
      } 
      fmt.Printf("consumer: %d\n", i) 
      i++ 
     } 
    } 
} 

Spielplatz: http://play.golang.org/p/fawEQnSDwB

+2

Alternativ, wenn die Struktur eine Scheibe enthielt, '[] int ', würde der Effekt der Übergabe der Scheibe (und damit der Struktur) nach Wert das interne Array nicht kopieren. Ich sage nicht, dass das deine Antwort ist. –

Antwort

11

Ja, alles, was eine Kopie in Go ist, können Sie leicht umgehen, dass durch den Kanalwechsel einen Zeiger (aka chan *largeStruct) zu verwenden.

// Demo: http://play.golang.org/p/CANxwt8s2B

Wie Sie sehen können, der Zeiger auf v.buf unterscheidet sich in jedem Fall, aber wenn Sie es chan *largeStruct ändern, werden die Zeiger gleich.

@LucasJones bereitgestellt ein wenig leichtes Beispiel zu folgen: https://play.golang.org/p/-VFWCgOnh0

Wie @nos darauf hingewiesen, gibt es ein Potential Rennen, wenn Sie den Wert in beiden goroutines ändern, nachdem es gesendet wird.

+3

Hier ist eine Demonstration der beiden Arten von Kanälen auf dem Spielplatz: https://play.golang.org/p/-VFWCgOnh0 –

+0

@LucasJones Ich werde dein Beispiel zur besseren Sichtbarkeit dem Beitrag hinzufügen. – OneOfOne

+2

Nur wenn Sie nur einen Zeiger senden, sollten Sie sich über mögliche Wettlaufbedingungen im Klaren sein. Sie wollen nicht mit beiden Goroutinen enden, die mit der gleichen Struktur unordentlich sind – nos

4

The Go Programming Language Specification

Send statements

Eine Sende Anweisung sendet einen Wert auf einem Kanal. Der Kanalausdruck muss vom Kanaltyp sein, die Kanalrichtung muss die Operationen senden können, und der Typ des zu sendenden Werts muss dem Elementtyp des Kanals zuweisbar sein.

Es handelt sich um eine Kopie, da der Wert durch Zuordnung zum Elementtyp des Kanals an den Kanal gesendet wird. Wenn der Wert eine Struktur ist, wird die Struktur kopiert. Wenn der Wert ein Zeiger auf eine Struktur ist, wird der Zeiger auf die Struktur kopiert.