简介: 本文即Go语言的那些坑三。
本文即Go语言的那些坑三。
不要对Go并发函数的执行时机做任何假设
请看下列的列子:
1import(2"fmt"3"runtime"4"time"5)6func main(){7names := []string{"lily","yoyo","cersei","rose","annei"}8for_,name:= range names{9go func(){10fmt.Println(name)11}()12}13runtime.GOMAXPROCS(1)14runtime.Gosched()15}
请问输出什么?
答案:
1annei2annei3annei4annei5annei
为什么呢?是不是有点诧异?
输出的都是“annei”,而“annei”又是“names”的最后一个元素,那么也就是说程序打印出了最后一个元素的值,而name对于匿名函数来讲又是一个外部的值。因此,我们可以做一个推断:虽然每次循环都启用了一个协程,但是这些协程都是引用了外部的变量,当协程创建完毕,再执行打印动作的时候,name的值已经不知道变为啥了,因为主函数协程也在跑,大家并行,但是在此由于names数组长度太小,当协程创建完毕后,主函数循环早已结束,所以,打印出来的都是遍历的names最后的那一个元素“annei”。
如何证实以上的推断呢?
其实很简单,每次循环结束后,停顿一段时间,等待协程打印当前的name便可。
1import(2"fmt"3"runtime"4"time"5)6func main(){7names := []string{"lily","yoyo","cersei","rose","annei"}8for_,name:= range names{9go func(){10fmt.Println(name)11}()12time.Sleep(time.Second)13}14runtime.GOMAXPROCS(1)15runtime.Gosched()16}
打印结果:
1lily2yoyo3cersei4rose5annei
以上我们得出一个结论,不要对“go函数”的执行时机做任何的假设,除非你确实能做出让这种假设成为绝对事实的保证。
假设T类型的方法上接收器既有T类型的,又有T指针类型的,那么就不可以在不能寻址的T值上调用T接收器的方法
请看代码,试问能正常编译通过吗?
1import(2"fmt"3)4type Lili struct{5Name string6}7func (Lili *Lili) fmtPointer(){8fmt.Println("poniter")9}10func (Lili Lili) fmtReference(){11fmt.Println("reference")12}13func main(){14li := Lili{}15li.fmtPointer()16}
答案:
点击链接,查看剩余内容
https://developer.aliyun.com/article/619547?utm_content=g_1000095782
关键字:Go语言 题 答案