Golang Go语言代码求解,求Golang大牛解读
func makethumbnail2(filename[]string){ ch:=make(chan struct{}) for _,file:=range filename{ file=file go func(){
fmt.Println(file)
thumbnail.ImageFile(file)
ch<- struct {}{}
}()
}
for range filename{
<-ch
}
} filename 为 100 个图片文件的地址 slice 。 输出是什么。
Golang Go语言代码求解,求Golang大牛解读
更多关于Golang Go语言代码求解,求Golang大牛解读的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
输出不就是每个文件名么
你需要找本书看一眼
更多关于Golang Go语言代码求解,求Golang大牛解读的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
不懂别瞎 bb 按照理解应该是输出第 99 个文件路径。但是实际上确实随机输出 4 个文件地址才输出第 99 个文件地址,为啥是这样呢。
这段代码输出第 99 个文件地址概率非常大,后面都是。跟循环和 gorountine 的切换有关。
另外 file := file ,就是每个文件了。
那说明前四个负责 printf 的 goroutine 被执行的时候 for 循环还没跑完。
- 贴代码的时候注意格式。你贴成这样鬼知道代码长啥样
2. 贴代码的时候把无关代码注释掉。比如 thumbnail.ImageFile(file)
3. 你上面贴的那一段代码格式化好以后大概长这样
===========================================
package main
import (
“fmt”
)
func makethumbnail2(filename []string) {
ch := make(chan struct{})
for _, file := range filename {
file = file
go func() {
fmt.Println(file)
//thumbnail.ImageFile(file)
ch <- struct{}{}
}()
}
for range filename {
<-ch
}
}
func main() {
var files []string
for i := 0; i < 100; i++ {
files = append(files, fmt.Sprintf(“file%d”, i))
}
makethumbnail2(files)
}
====================================
4. 下面来解答你的问题
1.1 你在 func() 里面 捕获了 file 变量。而 go 的捕获机制是按照引用捕获。 也就是说,如果我们在 func()外部改变 file 的值, func()内部的 file 也会受到影响
1.2 你的 func()是在另一个 goroutine 里面执行的。也就是说,一方面有 N 多个 func()在不同的 goroutine 里面执行。一方面第一个 for range 循环又在改变 file 的值。在第一个 for range 完成之前,你看到的输出应该是随缘产生的。而 for range 完成之后,则会输出最后一个文件名。
1.3 至于楼主的四个随机文件,那单纯是因为输出了 4 个文件以后,第一个 for range 完成了。
1.4 上面那段测试代码在我的环境下运行只输出了 10 个 file99
1.5 参考资料 https://www.goinggo.net/2014/06/pitfalls-with-closures-in-go.html
你是对的。
我可以这样理解吗? 可以把 range 循环体代码 和 go routine 代码 放在 2 个地方 。当 go routine 启动第一次执行时 range 已经跑了很多圈而起 go func 对 range 中的循环变量是引用捕获。如果 f:=file go func 中对 f 就是值捕获。
https://golang.org/doc/effective_go.html#channels
和楼主问的问题完全一样的例子
当 go routine 启动第一次执行时 range 已经跑了很多圈而起 go func 对 range 中的循环变量是引用捕获。
这句话可以这样理解
如果 f:=file go func 中对 f 就是值捕获。
go 中只有按引用捕获,所以如果在 go func 中引用 f 还是按引用捕获,只不过捕获的是 f 的引用。 go func 中的值会随着 f 变化而变化。
如果在 go func 中不想让捕获的值随着外部修改而变化的话应该把捕获的值当成一个参数传递。代码大概长这样
====================
func makethumbnail2(filename []string) {
ch := make(chan struct{})
for _, file := range filename {
go func(file string) {
fmt.Println(file)
//thumbnail.ImageFile(file)
ch <- struct{}{}
}(file)
}
for range filename {
<-ch
}
}
=================================
注意 go func 多了一个 file string 的参数,而 go func 结束的时候手动把 file 传递进去了。
因为 go func 有一个 file 参数,所以 go func 里面的 fmt.Println(file)的 file 实际上打印的是 go func 的参数。
而 go func 结束的时候在括号中传递的参数 file 是 for range 中当前的 file 。而 string 类型的参数是按照值的类型传递的。所以上面代码就会(无序)输出 file0 - file99
你说的给 go func 加的参数方式我知道。实际上如果在 go func 外面 加 f:=file 不给 fo func 加参数也可以实现。
unc makethumbnail2(filename []string) {
ch := make(chan struct{})
for _, file := range filename {
f:=file
go func() {
fmt.Println(file)
//thumbnail.ImageFile()
ch <- struct{}{}
}()
}
for range filename {
<-ch
}
}
结果看这里 thumbnail.ImageFile(file)
ch 这里只是等待所有 goroutine 完成而已
应该用 file := file ,这样才会新建一个变量,不然就一直用 for 里的循环变量了。 for + go 的新手常见错误……
我觉得这样子比较好理解
[PlayGround]( https://play.golang.org/p/8Uh3CvraIQ)
另, 楼主的file=file
加这句代码的意义是什么?
再另,楼主 10 楼的代码里面 应该是fmt.Println(f)
才会有遍历的效果就是了。。。
当然,我很乐意帮你解读Go语言代码。不过由于你并未提供具体的代码片段,我将给出一些通用的解读方法和建议,这些建议可以帮助你更好地理解Go代码。
-
理解基础结构:
- Go代码通常以包(package)为单位组织。首先,检查代码中的
package
声明,了解它属于哪个包。 - 接下来,查看
import
语句,了解代码依赖了哪些外部包。
- Go代码通常以包(package)为单位组织。首先,检查代码中的
-
阅读函数和变量:
- Go语言的函数声明清晰明了,形如
func FunctionName(parameters) (results) { ... }
。 - 变量声明使用
var
关键字,或者可以使用更简洁的:=
短变量声明方式。
- Go语言的函数声明清晰明了,形如
-
关注并发:
- Go语言以并发编程见长,注意代码中是否使用了goroutines(通过
go
关键字启动)和通道(channel)。 - 理解并发模式,如
sync.WaitGroup
、sync.Mutex
等同步机制。
- Go语言以并发编程见长,注意代码中是否使用了goroutines(通过
-
测试代码:
- Go语言强调测试,检查是否有测试文件(通常以
_test.go
结尾)。 - 使用
go test
命令运行测试,确保代码的正确性。
- Go语言强调测试,检查是否有测试文件(通常以
-
使用工具:
- 利用Go的工具链,如
go fmt
格式化代码,go lint
检查代码风格和质量。 - 使用IDE或编辑器插件,如VSCode的Go插件,可以提供代码补全、错误提示等功能。
- 利用Go的工具链,如
如果你能提供具体的代码片段,我可以给出更详细的解读。希望这些建议对你有所帮助!