请帮帮我。 我有块代码,它使用迭代来获取地图的元素,并使用这个元素在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)
}
它符合我的期望,是什么导致了这种差异?谢谢你的解释。
答案 0 :(得分:0)
在第一个版本中,你的goroutine使用变量srv
(和k
),它随着循环的每次迭代而变化,所以你不知道你的goroutine会看到什么值。执行。在第二个版本中,您将srv
作为参数传递给goroutine,因此goroutine中的变量srv
不再是循环中使用的变量。