2013-08-01 25 views
5

Ich versuche, das Problem auf dieser Folie skizzierte zu verstehen:Wie wird dieser chan geleckt?

http://talks.golang.org/2013/bestpractices.slide#27

Kopieren Sie den Code, falls die URL stirbt:

func sendMsg(msg, addr string) error { 
    conn, err := net.Dial("tcp", addr) 
    if err != nil { 
     return err 
    } 
    defer conn.Close() 
    _, err = fmt.Fprint(conn, msg) 
    return err 
} 

func broadcastMsg(msg string, addrs []string) error { 
    errc := make(chan error) 
    for _, addr := range addrs { 
     go func(addr string) { 
      errc <- sendMsg(msg, addr) 
      fmt.Println("done") 
     }(addr) 
    } 

    for _ = range addrs { 
     if err := <-errc; err != nil { 
      return err 
     } 
    } 
    return nil 
} 

func main() { 
    addr := []string{"localhost:8080", "http://google.com"} 
    err := broadcastMsg("hi", addr) 

    time.Sleep(time.Second) 

    if err != nil { 
     fmt.Println(err) 
     return 
    } 
    fmt.Println("everything went fine") 
} 

Und die Kommentare:

  • die goroutine ist auf dem chan gesperrt
  • die goroutine enthält einen bezug auf t er chan
  • die chan wird Müll nie

gesammelt Ich bin nicht sicher, ob ich verstehen, warum die chan nie oder welche goroutine gesammelt wird ein Verweis auf die chan zu halten. Ihre Zeit ist willkommen!

Antwort

5

The Go Programming Language Specification

Function literals

A Funktionsliteral stellt eine anonyme Funktion.

Ein Funktionsliteral kann einer Variablen zugewiesen oder direkt aufgerufen werden.

f := func(x, y int) int { return x + y } 
func(ch chan int) { ch <- ACK }(replyChan) 

Funktionsliterale sind Schließungen: sie Variablen in eine umgebende Funktion definiert beziehen. Diese Variablen werden dann zwischen der Umgebungsfunktion und dem Funktionsliteral gemeinsam genutzt, und sie bleiben als erhalten, solange sie zugänglich sind.

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.

SendStmt = Channel "<-" Expression . 
Channel = Expression . 

Sowohl der Kanal und der Wert Ausdruck ausgewertet werden, bevor Kommunikation beginnt. Kommunikationsblöcke, bis der Sendevorgang fortgesetzt werden kann. Ein Send auf einem ungepufferten Kanal kann fortfahren, wenn ein Empfänger bereit ist. Ein Senden auf einem gepufferten Kanal kann fortfahren, wenn im Puffer Platz ist. Ein Sendevorgang auf einem geschlossenen Kanal wird fortgesetzt, indem eine Laufzeit panic verursacht wird. A senden auf einen nil Kanal blockiert für immer.

Es gibt nur eine go Aussage, go func(addr string), und es ist ein Verschluss über den Kanal variable errc.

func broadcastMsg(msg string, addrs []string) error { 
    errc := make(chan error) 
    for _, addr := range addrs { 
     go func(addr string) { 
      errc <- sendMsg(msg, addr) 
      fmt.Println("done") 
     }(addr) 
    } 

    for _ = range addrs { 
     if err := <-errc; err != nil { 
      return err 
     } 
    } 
    return nil 
} 

Zwei goroutines sind seit len(addrs) == 2 gestartet.Wegen eines vorzeitigen Beendens, wenn err != nil beim ersten Empfang auf Kanal errc, nur eine Goroutine abgeschlossen ist. Die zweite Goroutine ist beim Senden (Schreiben) in den ungepufferten Kanal errc blockiert; es wird nie abgeschlossen. Daher gibt es immer noch einen Verweis auf errc, so dass es nie Müll gesammelt wird. Die zweite Goroutine wird schließlich verlassen, wenn das Programm beendet wird.

Verwandte Themen