面试题笔试题学习日记——golang(8.02-2)

写出下面代码的输出内容
package main

import "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结束后才会向上传递。出现panic恐慌时候,会先按照defer的后入先出的顺序执行,最后才执行panic。

打印后
打印中
打印前
panic:触发异常
以下代码有什么问题,说明原因
type student struct {
	Name string
	Age int
}

func pase_student(){
	m := make(map[string]*student)
	stus := []student{
		{Name:"zhou",Age:24},
		{Name:"h",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[stirng]*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 {
		fmt.Println(k, "=>", v.Name)
	}

	//正确写法
	for i := 0; i < len(stus); i++ {
		m[stus[i].Name] = &stus[i]
	}
	for k, v := range m {
		fmt.Println(k, "=>", v.Name)
	}
}
下面代码会输出什么,并说明原因
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:均为输出10,B:从0~9输出(顺序不定)。第一个go func中i是外部for的一个变量,地址不变化。遍历完成后,最终i=10.。故go func执行时,i的值始终是10。
第二个go func中i是函数参数,与外部for中的i完全是两个变量。尾部(i)将发生值拷贝,go func内部指向值拷贝地址。

下面代码会输出什么?

type People struct {
}
func (p *People) ShowA() {
	fmt.Println("show A")
	p.ShowB()
}
func (p *People) ShowB() {
	fmt.Println("show B")
}
type Teacher struct {
	People
}
func (t *Teacher) ShowB() {
	fmt.Println("teacher show B")
}
func main() {
	t := Teacher{}
	t.ShowA()
}

考点:go的组合继承
解答:这是Golang的组合模式,可以实现OOP的继承,被组合的类型People所包含的方法虽然升级成了外部类型Teacher这个组合类型的方法(一定要是匿名字段),但它们的方法(ShowA())调用时接受者并没有发生变化。此时People类型并不知道他们会变什么类型组合,当然也就无法调用方法时去使用未知的组合者Teacher类型的功能。

showA
showB
下面代码会触发异常吗?请详细说明
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”块。

你可能感兴趣的:(golang,go)