2013-08-01 48 views
5

我想了解概述本幻燈片上的問題:這個陳如何泄露?

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

複製的情況下,URL死亡代碼:

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

與點評:

  • goroutine在chan上被阻止寫入
  • 該goroutine持有對t的引用他瓚
  • 陳女士將永遠不會被垃圾收集

我不知道我明白爲什麼陳永遠不會被收集或夠程被保持到陳的參考。感謝您的時間!

回答

5

The Go Programming Language Specification

Function literals

字面的函數表示匿名功能。

FunctionLit = "func" Function . 

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

函數literal可以賦給變量或直接調用。

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

功能文本是封閉件:它們可以是指在 周圍函數定義的變量。然後這些變量在 周圍函數和函數文字之間共享,並且它們在 之後仍然可以存活。

Send statements

甲發送語句的頻道上發送的值。通道表達式 必須是通道類型,通道方向必須允許發送 操作,並且要發送的值的類型必須可分配給通道的元素類型爲 。

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

通信開始前兩個通道和值表達進行評估。通信阻塞,直到發送可以繼續。 如果接收器準備就緒,可以繼續發送無緩衝的信道。如果緩衝區中有空間,則可以繼續在緩衝的信道上發送 。 通過運行時間panic繼續發送關閉的通道。 A 永遠發送nil頻道塊。

只有一個go聲明,go func(addr string),它是通過信道變量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 
} 

len(addrs) == 2以來,兩個套房開始啓動。由於err != nilerrc頻道首次接收時提早退出,因此只有一個goroutine完成。第二個goroutine在發送(寫入)到無緩衝通道errc上時被阻塞;它永遠不會完成。因此,仍然有參考errc,所以它從來沒有垃圾收集。當程序退出時,第二個參數最終被放棄。