gpt4 book ai didi

concurrency - 这个chan是怎么泄露的?

转载 作者:IT王子 更新时间:2023-10-29 01:27:21 26 4
gpt4 key购买 nike

我试图理解这张幻灯片上概述的问题:

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 在写入时被阻塞
  • goroutine 持有对 chan 的引用
  • chan 永远不会被垃圾回收

我不确定我是否理解为什么 chan 从未被收集或哪个 goroutine 保留对 chan 的引用。感谢您的宝贵时间!

最佳答案

The Go Programming Language Specification

Function literals

A function literal represents an anonymous function.

FunctionLit = "func" Function .

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

A function literal can be assigned to a variable or invoked directly.

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

Function literals are closures: they may refer to variables defined in a surrounding function. Those variables are then shared between the surrounding function and the function literal, and they survive as long as they are accessible.

Send statements

A send statement sends a value on a channel. The channel expression must be of channel type, the channel direction must permit send operations, and the type of the value to be sent must be assignable to the channel's element type.

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

Both the channel and the value expression are evaluated before communication begins. Communication blocks until the send can proceed. A send on an unbuffered channel can proceed if a receiver is ready. A send on a buffered channel can proceed if there is room in the buffer. A send on a closed channel proceeds by causing a run-time panic. A send on a nil channel blocks forever.

只有一个go声明,go func(addr string) ,它是 channel 变量 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起启动了两个goroutines .由于在 err != nil 时过早退出在 channel 上第一次接收 errc ,只有一个 goroutine 完成。第二个 goroutine 在发送(写入)到无缓冲 channel 时被阻塞 errc ;它永远不会完成。所以还是有引用errc ,所以它永远不会被垃圾收集。当程序退出时,第二个 goroutine 最终被放弃。

关于concurrency - 这个chan是怎么泄露的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17983699/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com