gpt4 book ai didi

go - 为什么我通过循环创建goroutine会出现这种情况?

转载 作者:数据小太阳 更新时间:2023-10-29 03:42:17 28 4
gpt4 key购买 nike

请帮帮我。我有 block 代码,它使用迭代来获取 map 的元素,并使用这个元素在 Linux 机器上的端口上创建一个监听器,但它的执行超出了我的预期。代码如下:

var srvs = map[string]struct {
id int
timezone string
connCfg string
conn net.Conn
}{"BrazilEastSrv": {id: 1, timezone: "Brazil/East", connCfg: "127.0.0.1:9007"},
"AustraliaDarwinSrv": {id: 2, timezone: "Australia/Darwin", connCfg: "127.0.0.1:9008"}}

var ch1 = make(chan int, 2)

func main() {
for k, srv := range srvs {
go func() {
if ln, err := net.Listen("tcp", srv.connCfg); err != nil {
log.Fatal(fmt.Sprintf("%s : %s conn failed,", k, srv.connCfg))
} else {
log.Println(fmt.Sprintf("%s:%s created, port:%s listened.", k, srv.connCfg[:9], srv.connCfg[10:]))
if conn, err := ln.Accept(); err != nil {
log.Fatal(srv.connCfg, " conn create fatal, errmsg=", err)
} else {
srv.conn = conn
defer srv.conn.Close()
log.Println("Accepted an access request from cli:", srv.conn.RemoteAddr(), ".")
handleMsg(srv)
}
}
}()
}
var brazilEastSrv, australiaDarwinSrv = <-ch1
log.Println(brazilEastSrv, australiaDarwinSrv)
}

输出:

2017/12/07 11:45:48 AustraliaDarwinSrv:127.0.0.1 created, port:9008 listened.
2017/12/07 11:45:48 AustraliaDarwinSrv : 127.0.0.1:9008 conn failed,
exit status 1

从输出内容看。它使用迭代的最后一个元素并重用这个元素,为什么会出现这个问题?

但是当我做一些改变时:

var srvs = map[string]struct {
id int
timezone string
connCfg string
conn net.Conn
}{"BrazilEastSrv": {id: 1, timezone: "Brazil/East", connCfg: "127.0.0.1:9007"},
"AustraliaDarwinSrv": {id: 2, timezone: "Australia/Darwin", connCfg: "127.0.0.1:9008"}}

var ch1 = make(chan int, 2)

func main() {
for k, srv := range srvs {
go func(srv struct {
id int
timezone string
connCfg string
conn net.Conn
}) {
//go func() {
if ln, err := net.Listen("tcp", srv.connCfg); err != nil {
log.Fatal(fmt.Sprintf("%s : %s conn failed,", k, srv.connCfg))
} else {
log.Println(fmt.Sprintf("%s:%s created, port:%s listened.", k, srv.connCfg[:9], srv.connCfg[10:]))
if conn, err := ln.Accept(); err != nil {
log.Fatal(srv.connCfg, " conn create fatal, errmsg=", err)
} else {
srv.conn = conn
defer srv.conn.Close()
log.Println("Accepted an access request from cli:", srv.conn.RemoteAddr(), ".")
handleMsg(srv)
}
}
//}()
}(srv)
}
var brazilEastSrv, australiaDarwinSrv = <-ch1
log.Println(brazilEastSrv, australiaDarwinSrv)
}

它的表现符合我的预期,是什么导致了这种差异?谢谢你的解释。

最佳答案

在第一个版本中,你的 goroutine 使用变量 srv(和 k)随着循环的每次迭代而改变,所以你不知道你的值是多少goroutine 将在执行时看到。在第二个版本中,您将 srv 作为参数传递给 goroutine,因此 goroutine 中的变量 srv 不再是循环中使用的同一个变量.

关于go - 为什么我通过循环创建goroutine会出现这种情况?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47687604/

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