2016-05-30 6 views
2

Ich erstelle einen einfachen Kanal, der Zeichenfolgenwerte verwendet. Aber anscheinend schiebe ich jeden Buchstaben in der Zeichenfolge anstelle der ganzen Zeichenfolge in jeder Schleife.Go-Kanal nimmt jeden Buchstaben als Zeichenfolge anstelle der gesamten Zeichenfolge

Ich vermisse wahrscheinlich etwas sehr grundlegendes. Was mache ich falsch ?

https://play.golang.org/p/-6E-f7ALbD

Code:

func doStuff(s string, ch chan string) { 
    ch <- s 
} 

func main() { 
    c := make(chan string) 
    loops := [5]int{1, 2, 3, 4, 5} 

    for i := 0; i < len(loops); i++ { 
     go doStuff("helloooo", c) 
    } 

    results := <-c 

    fmt.Println("channel size = ", len(results)) 

    // print the items in channel 
    for _, r := range results { 
     fmt.Println(string(r)) 
    } 
} 

Antwort

4

Ihr Code sendet string s auf dem Kanal richtig:

func doStuff(s string, ch chan string){ 
    ch <- s 
} 

Das Problem ist auf der Empfängerseite:

results := <- c 

fmt.Println("channel size = ", len(results)) 

// print the items in channel 
for _,r := range results { 
    fmt.Println(string(r)) 
} 

results ist ein einzelner Wert, der vom Kanal empfangen wird (der erste Wert, der darauf gesendet wird). Und Sie drucken die Länge dieser string.

Dann Schleife über diese Zeichenfolge (results) mit einer for range, die über seine rune s Schleifen, und Sie drucken diese.

Was Sie wollen, ist eine Schleife über den Werten des Kanals:

// print the items in channel 
for s := range c { 
    fmt.Println(s) 
} 

Das bei der Ausführung in einer Laufzeit Panik führen:

fatal error: all goroutines are asleep - deadlock! 

Weil Sie nie den Kanal schließen, und ein for range auf einem Kanal läuft, bis der Kanal geschlossen ist. Also musst du den Kanal irgendwann schließen.

Zum Beispiel lassen Sie uns 1 Sekunde warten, schließen Sie es dann:

go func() { 
    time.Sleep(time.Second) 
    close(c) 
}() 

Auf diese Weise Ihre App wird nach 1 Sekunde ausführen und beenden. Versuchen Sie es auf der Go Playground.

Eine andere, schönere Lösung ist sync.WaitGroup zu verwenden: Dies wartet, bis alle goroutines fertig sind (Senden eines Wertes auf dem Kanal), dann schließt es den Kanal (es gibt also keine unnötige Wartezeit/Verzögerung).

var wg = sync.WaitGroup{} 

func doStuff(s string, ch chan string) { 
    ch <- s 
    wg.Done() 
} 

// And in main(): 
for i := 0; i < len(loops); i++ { 
    wg.Add(1) 
    go doStuff("helloooo", c) 
} 
go func() { 
    wg.Wait() 
    close(c) 
}() 

Versuchen Sie dieses auf dem Go Playground.

Hinweise:

etwas 5-mal zu wiederholen, brauchen Sie nicht, dass hässliche loops Array.Einfach tun:

for i := 0; i < 5; i++ { 
    // Do something 
} 
+0

Vielen Dank für die detaillierte Information. – Sudhakar

0

Der Grund, warum Sie statt Zeichenfolge, die Buchstaben werden immer wieder, dass Sie den Kanal Ergebnis einer Variablen und Iteration über das Ergebnis des Kanals auf diese Variable, die eine in Ihrem Fall zugewiesen werden Zuweisen string, und in Go können Sie mit einer for range Schleife über eine Zeichenfolge iterieren, um die Runen zu erhalten.

Sie können den Kanal einfach drucken, ohne über das Kanalergebnis zu iterieren.

package main 

import (
    "fmt" 
) 

func doStuff(s string, ch chan string){ 
    ch <- s 
} 

func main() { 
    c := make(chan string) 
    loops := [5]int{1,2,3,4,5} 

    for i := 0; i < len(loops) ; i++ { 
     go doStuff("helloooo", c)  
    } 

    results := <- c 
    fmt.Println("channel size = ", len(results)) 
    fmt.Println(results) // will print helloooo 
}