1 写出下面代码输出内容。
package main import ( "fmt" ) funcmain() { defer_call() } funcdefer_call() { deferfunc() {fmt.Println("打印前")}() deferfunc() {fmt.Println("打印中")}() deferfunc() {fmt.Println("打印后")}() panic("触发异常") }
考点:defer执行顺序 解答: defer 是后进先出。 panic 需要等defer 结束后才会向上传递。 出现panic恐慌时候,会先按照defer的后入先出的顺序执行,最后才会执行panic。
打印后 打印中 打印前 panic: 触发异常
2 以下代码有什么问题,说明原因。
type student struct { Name string Age int } funcpase_student() { m := make(map[string]*student) stus := []student{ {Name: "zhou",Age: 24}, {Name: "li",Age: 23}, {Name: "wang",Age: 22}, } for _,stu := range stus { m[stu.Name] =&stu } }
考点:foreach 解答: 这样的写法初学者经常会遇到的,很危险! 与Java的foreach一样,都是使用副本的方式。所以m[stu.Name]=&stu实际上一致指向同一个指针, 最终该指针的值为遍历的最后一个struct的值拷贝。 就像想修改切片元素的属性:
for _, stu := rangestus { stu.Age = stu.Age+10}
也是不可行的。 大家可以试试打印出来:
func pase_student() { m := make(map[string]*student) stus := []student{ {Name: "zhou",Age: 24}, {Name: "li",Age: 23}, {Name: "wang",Age: 22}, } // 错误写法 for _,stu := range stus { m[stu.Name] =&stu } fork,v:=range m{ println(k,"=>",v.Name) } // 正确 for i:=0;i",v.Name) } }
3 下面的代码会输出什么,并说明原因
func main() { runtime.GOMAXPROCS(1) wg := sync.WaitGroup{} wg.Add(20) for i := 0; i < 10; i++ { gofunc() { fmt.Println("A: ", i) wg.Done() }() } for i:= 0; i < 10; i++ { gofunc(i int) { fmt.Println("B: ", i) wg.Done() }(i) } wg.Wait() }
考点:go执行的随机性和闭包 解答: 谁也不知道执行后打印的顺序是什么样的,所以只能说是随机数字。 但是A:均为输出10,B:从0~9输出(顺序不定)。 第一个go func中i是外部for的一个变量,地址不变化。遍历完成后,最终i=10。 故go func执行时,i的值始终是10。
第二个go func中i是函数参数,与外部for中的i完全是两个变量。 尾部(i)将发生值拷贝,go func内部指向值拷贝地址。
4 下面代码会输出什么?
type People struct{}func (p People)ShowA() { fmt.Println("showA") p.ShowB() } func(pPeople)ShowB() { fmt.Println("showB") } typeTeacher struct { People } func(t*Teacher)ShowB() { fmt.Println("teachershowB") } funcmain() { t := Teacher{} t.ShowA() }
考点:go的组合继承 解答: 这是Golang的组合模式,可以实现OOP的继承。 被组合的类型People所包含的方法虽然升级成了外部类型Teacher这个组合类型的方法(一定要是匿名字段),但它们的方法(ShowA())调用时接受者并没有发生变化。 此时People类型并不知道自己会被什么类型组合,当然也就无法调用方法时去使用未知的组合者Teacher类型的功能。 showAshowB
5 下面代码会触发异常吗?请详细说明
func main() { runtime.GOMAXPROCS(1) int_chan := make(chanint, 1) string_chan := make(chanstring, 1) int_chan
考点:select随机性 解答: select会随机选择一个可用通用做收发操作。 所以代码是有肯触发异常,也有可能不会。 单个chan如果无缓冲时,将会阻塞。但结合 select可以在多个chan间等待执行。有三点原则:
select 中只要有一个case能return,则立刻执行。 当如果同一时间有多个case均能return则伪随机方式抽取任意一个执行。 如果没有一个case能return则可以执行”default”块。
6 下面代码输出什么?
funccalc(indexstring, a, bint) int { ret := a+ b fmt.Println(index,