Golang Block 到底是什么? 怎么就能解决闭包变量冲突了?

共 1242字,需浏览 3分钟

 ·

2023-02-10 20:27

每天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

  1. 用 括号 {} 包围的一个代码块。

  2. 这个代码块内容也可以为空, 也可以是有内容。

Block = "{" StatementList "}" .
StatementList = { Statement ";" } .

他存在于所有大括号使用的地方,比如变量定义、函数定义等等,预示着作用域!

因此, 在 22 行 i:=i 是合法的, 在 statement block 中产生了 同名变量覆盖

也就是因为 {} 是 for 子block 的原因, for 的 post 可以修改变量 i, 在 statement 中也可以修改变量 i。

所以,大家在使用 {}的时候要注意,如果内部有嵌套的block,在外部变量传递的时候,必须加临时变量副本,防止意外发生。

你好,我是小熊,是一个爱技术但是更爱钱的程序员。上进且佛系自律的人。喜欢发小秘密/臭屁又爱炫耀。

奋斗的大学,激情的现在。赚了钱买了房写了书出了名。当过面试官,带过徒弟搬过砖。

大厂外来务工人员。是我,我是小熊,是不一样的烟火欢迎围观。

关注我加Go群、加大厂群学习交流一起进步!


浏览 17
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报