go语言错题整理及答案

简介: 本文即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语言   题   答案

你可能感兴趣的:(go语言错题整理及答案)