点击这里,查看剩余6道面试题及其解析
简介: 最近在很多地方看到了go语言的面试题,看到了很多人对Go语言的面试题心存恐惧,也是为了复习基础,我把解题的过程总结下来。
Go语言最新面试题及其解析 1、写出下面代码输出内容。
package mainimport ( "fmt")func main() { defer_call()}func defer_call() { defer func() { fmt.Println("打印前") }() defer func() { fmt.Println("打印中") }() defer func() { fmt.Println("打印后") }() panic("触发异常")}
考点:defer执行顺序 解答: defer 是后进先出。 协程遇到panic时,遍历本协程的defer链表,并执行defer。在执行defer过程中,遇到recover则停止panic,返回recover处继续往下执行。如果没有遇到recover,遍历完本协程的defer链表后,向stderr抛出panic信息。从执行顺序上来看,实际上是按照先进后出的顺序执行defer
打印后 打印中 打印前 panic: 触发异常 注意:请用独立终端运行,排查某些IDE对stderr和stdout处理问题导致输出顺序不一致。
2、以下代码有什么问题,说明原因。
type student struct { Name string Age int}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 }}
考点:foreach 解答: 这样的写法初学者经常会遇到的,很危险! 与Java的foreach一样,都是使用副本的方式。所以m[stu.Name]=&stu实际上一致指向同一个指针, 最终该指针的值为遍历的最后一个struct的值拷贝。 就像想修改切片元素的属性:
for _, stu := range stus { 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 } for k,v:=range m{ println(k,"=>",v.Name) } // 正确 for i:=0;i<len(stus);i++ { m[stus[i].Name] = &stus[i] } for k,v:=range m{ println(k,"=>",v.Name) }}
3、下面的代码会输出什么,并说明原因
func main() { runtime.GOMAXPROCS(1) wg := sync.WaitGroup{} wg.Add(20) for i := 0; i < 10; i++ { go func() { fmt.Println("A: ", i) wg.Done() }() } for i := 0; i < 10; i++ { go func(i int) { fmt.Println("B: ", i) wg.Done() }(i) } wg.Wait()}
考点:go执行的随机性和闭包 解答: 谁也不知道执行后打印的顺序是什么样的,所以只能说是随机数字。
其中A:输出完全随机,取决于goroutine执行时i的值是多少;
而B:一定输出为0~9,但顺序不定。
第一个go func中i是外部for的一个变量,地址不变化,但是值都在改变。
第二个go func中i是函数参数,与外部for中的i完全是两个变量。 尾部(i)将发生值拷贝,go func内部指向值拷贝地址。
所以在使用goroutine在处理闭包的时候,避免发生类似第一个go func中的问题。
4、下面代码会输出什么?
type People struct{}func (p *People) ShowA() { fmt.Println("showA") p.ShowB()}func (p *People) ShowB() { fmt.Println("showB")}type Teacher struct { People}func (t *Teacher) ShowB() { fmt.Println("teacher showB")}func main() { t := Teacher{} t.ShowA()}
考点:go的组合继承 解答: 这是Golang的组合模式,可以实现OOP的继承。 被组合的类型People所包含的方法虽然升级成了外部类型Teacher这个组合类型的方法(一定要是匿名字段),但它们的方法(ShowA())调用时接受者并没有发生变化。 此时People类型并不知道自己会被什么类型组合,当然也就无法调用方法时去使用未知的组合者Teacher类型的功能。
showAshowB 5、下面代码会触发异常吗?请详细说明
func main() { runtime.GOMAXPROCS(1) int_chan := make(chan int, 1) string_chan := make(chan string, 1) int_chan <- 1 string_chan <- "hello" select { case value := <-int_chan: fmt.Println(value) case value := <-string_chan: panic(value) }}
考点:select随机性 解答: select会随机选择一个可用通用做收发操作。 所以代码是有肯触发异常,也有可能不会。 单个chan如果无缓冲时,将会阻塞。但结合 select可以在多个chan间等待执行。有三点原则: select 中只要有一个case能return,则立刻执行。 当如果同一时间有多个case均能return则伪随机方式抽取任意一个执行。 * 如果没有一个case能return则可以执行”default”块。
关键字:go语言 面试
钉钉扫码进群,阿里云等各界大佬等着你哦~