2013-08-01 18 views
5

Próbuję zrozumieć problem przedstawionej na tym slajdzie:Jak to wyciek ten kanał?

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

skopiowaniu kodu w przypadku, gdy adres URL pieczątki:

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") 
} 

a komentarze:

  • goroutine jest zablokowany na chan napisać
  • Goroutine ma odniesienie do t on chan
  • Chan nigdy nie będą zbierane śmieci

Nie jestem pewien, czy rozumiem, dlaczego nigdy chan zostaje pobrane lub które goroutine utrzymuje odniesienie do chan. Twój czas jest doceniany!

Odpowiedz

5

The Go Programming Language Specification

Function literals

Funkcja dosłownym oznacza anonimową funkcję.

FunctionLit = "func" Function . 

func(a, b int, z float64) bool { return a*b < int(z) } 

Literał funkcji można przypisać do zmiennej lub wywołać bezpośrednio.

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

literały funkcyjne są zamknięcia: mogą one odnosić się do zmiennych zdefiniowanych w otaczającą funkcyjnego. Zmienne te są następnie dzielone między funkcję otaczającą i literalną funkcji, i zachowują się tak długo, jak są dostępne.

Send statements

Oświadczenie wyślij wysyła wartość na kanale. Wyrażenie kanału musi być typu kanału, kierunek kanału musi umożliwiać wysyłanie operacji , a typ wysyłanej wartości musi być przypisany do typu elementu kanału.

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

Zarówno kanał i wyrażenie wartości są oceniane przed rozpoczęciem komunikacja. Bloki komunikacji do momentu wysłania wiadomości. Wysłanie kanału niebuforowanego może być kontynuowane, jeśli odbiornik jest gotowy. A wysłać na buforowany kanał można kontynuować, jeśli jest miejsce w buforze. Wysłanie na zamkniętym kanale następuje przez spowodowanie czasu wykonywania panic. A wysyła na zawsze bloki kanałowe nil.

Jest tylko jeden go oświadczenie, go func(addr string), i jest to zamknięcie na zmiennej kanału 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 
} 

Dwa goruteiny są uruchamiane od len(addrs) == 2.Ze względu na przedwczesne zakończenie przy err != nil na pierwszym odbiorze na kanale errc, kończy się tylko jedna goroutina. Druga goroutine jest zablokowana przy wysyłaniu (zapis) do niebuforowanego kanału errc; nigdy się nie kończy. Dlatego nadal istnieje odniesienie do errc, więc nigdy nie jest zbierane śmieci. Druga goryntyna zostaje ostatecznie porzucona, gdy program się kończy.