Golang Block 到底是什么? 怎么就能解决闭包变量冲突了?
每天9点准时发文 喜欢给个星标
什么?你告诉我 i:=i
不仅合法,而且还常用。甚至能解决并发编程中的变量冲突?刚看到这句话我都快蒙了。
以下这段代码出自 golang 官方
的 Effective GO
并发编程章节。为了解决 goroute 中变量 req
冲突, 使用了语句 req := req
https://golang.org/doc/effective_go#concurrency
func Serve(queue chan *Request) {
for req := range queue {
req := req // Create new instance of req for the goroutine.
sem <- 1
go func() {
process(req)
<-sem
}()
}
}
req := req
这种写法是不是感到很奇怪?看看 Effective GO
怎么说?
不仅合法,而且还常用。这么做是为了在循环体内部将得到一个同名变量, 以隐藏 循环变量 req, 从而每个 goroute 得到一个唯一
req
。
直接这么看,还是有点拗口。不过不重要, 在了解了 golang 的 区块(block) 定义范围之后, 就迎刃而解了。
Blocks
https://golang.org/ref/spec#Blocks
什么是 Blocks
?
用 大括号
{}
包围的一个代码块。这个代码块内容也可以为空, 也可以是有内容。
Block = "{" StatementList "}" .
StatementList = { Statement ";" } .
他存在于所有大括号使用的地方,比如变量定义、函数定义等等,预示着作用域!
因此, 在 22 行 i:=i
是合法的, 在 statement block
中产生了 同名变量覆盖
。
也就是因为 {} 是 for 子block 的原因, for 的 post 可以修改变量 i, 在 statement 中也可以修改变量 i。
所以,大家在使用 {}
的时候要注意,如果内部有嵌套的block
,在外部变量传递的时候,必须加临时变量副本,防止意外发生。
你好,我是小熊,是一个爱技术但是更爱钱的程序员。上进且佛系自律的人。喜欢发小秘密/臭屁又爱炫耀。
奋斗的大学,激情的现在。赚了钱买了房,写了书出了名。当过面试官,带过徒弟搬过砖。
大厂外来务工人员。是我,我是小熊,是不一样的烟火欢迎围观。