Skip to content

Latest commit

 

History

History
335 lines (280 loc) · 6.46 KB

卷1.md

File metadata and controls

335 lines (280 loc) · 6.46 KB

目前卷一正在完成中,有些答案没有添加或校验。希望广大gopher可以一同完成....

1、写出下面代码输出结果(20分)

package main

import (
	"fmt"
)

func main() {
	defer_call()
}

func defer_call() {
	defer func() { fmt.Println("打印前") }()
	defer func() { fmt.Println("打印中") }()
	defer func() { fmt.Println("打印后") }()

	panic("触发异常")
}

2、以下代码有什么问题,说明原因(20分)

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
	}
}

3、下面的代码会输出什么,并说明原因(20分)

func main() {
	runtime.GOMAXPROCS(1)
	wg := sync.WaitGroup{}
	wg.Add(20)
	for i := 0; i < 10; i++ {
		go func() {
			fmt.Println("i: ", i)
			wg.Done()
		}()
	}
	for i := 0; i < 10; i++ {
		go func(i int) {
			fmt.Println("i: ", i)
			wg.Done()
		}(i)
	}
	wg.Wait()
}

4、下面代码会输出什么?(20分)

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()
}

5、下面代码会触发异常吗?请详细说明(20分)

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)
	}
}

6、下面代码会输出什么?(20分)

func calc(index string, a, b int) int {
	ret := a + b
	fmt.Println(index, a, b, ret)
	return ret
}

func main() {
	a := 1
	b := 2
	defer calc("1", a, calc("10", a, b))
	a = 0
	defer calc("2", a, calc("20", a, b))
	b = 1
}

7、请写出以下输出内容(20分)

func main() {
	s := make([]int, 5)
	s = append(s, 1, 2, 3)
	fmt.Println(s)
}

8、下面的代码有什么问题(20分)

type UserAges struct {
	ages map[string]int
	sync.Mutex
}

func (ua *UserAges) Add(name string, age int) {
	ua.Lock()
	defer ua.Unlock()
	ua.ages[name] = age
}

func (ua *UserAges) Get(name string) int {
	if age, ok := ua.ages[name]; ok {
		return age
	}
	return -1
}

9、下面的迭代会有什么问题?(20分)

func (set *threadSafeSet) Iter() <-chan interface{} {
	ch := make(chan interface{})
	go func() {
		set.RLock()

		for elem := range set.s {
			ch <- elem
		}

		close(ch)
		set.RUnlock()

	}()
	return ch
}

10、以下代码能编译过去吗?为什么?(20分)

package main

import (
	"fmt"
)

type People interface {
	Speak(string) string
}

type Student struct{}

func (stu *Student) Speak(think string) (talk string) {
	if think == "bitch" {
		talk = "You are a good boy"
	} else {
		talk = "hi"
	}
	return
}

func main() {
	var peo People = Student{}
	think := "bitch"
	fmt.Println(peo.Speak(think))
}

参考答案

第1题

考点:defer执行顺序,panic的执行方式

结果:

打印后
打印中
“触发异常”
打印前

解析:“触发异常”可能出现在任何位置。defer是先进后出,逆序执行。 笔者猜测:panic()函数相当与go出去的一个协程,相关资料:https://blog.golang.org/defer-panic-and-recover, 将马上更新

第2题

解析:

在range循环中,变量是不会随着遍历过程发生变化的。
因此在代码中stu是不会变化的,变化的是放在&stu地址上的数据,
因此最后m中value都将是最后一个放在&stu中的值

第3题

解析:

先说说WaitGroup的用途:它能够一直等到所有的goroutine执行完成,并且阻塞主线程的执行,直到所有的goroutine执行完成。
这里要注意一下,他们的执行结果是没有顺序的,调度器不能保证多个 goroutine 执行次序,且进程退出时不会等待它们结束。
WaitGroup总共有三个方法:Add(delta int),Done(),Wait()。简单的说一下这三个方法的作用。
Add:添加或者减少等待goroutine的数量
Done:相当于Add(-1)
Wait:执行阻塞,直到所有的WaitGroup数量变成0

第4题

结果:

showA
showB

解析:

首先明确一点 go中没有继承关系。也不应该提及“继承”这个词,其中Trecher并没有继承Propler,而是嵌套People,
而t.ShowA()是一个语法糖,其实t.ShowA() = t.people.ShowA(),也就是说在嵌套结构中,go会优先调用本身方法,
如果本身没有此方法,就回去调用其所包含结构的方法。

本题中,showA()是Teacher不具有的,但是它所嵌套的People具有,因此回调用People.showA(),People.showA()
中调用了*People 的showB()当然会展示“shwoB”,而不是“teacher showB”

引申一点,
如果嵌套有两个结构,并且两个结构具有相同的方法,如何执行的?
例如:
type People struct{}

func (p *People) ShowA() {
	fmt.Println("showA")
	p.ShowB()
}
func (p *People) ShowB() {
	fmt.Println("showB")
}

type Human struct{}

func (h *Human) ShowA() {
    fmt.Println("Human showA")
}

type Teacher struct {
	Human
	People
}

func (t *Teacher) ShowB() {
	fmt.Println("teacher showB")
}

func main() {
	t := Teacher{}
	t.ShowA()
}


答案是 编译报错,不支持这种情况的。

第6题

结果:

10 1 2 3
20 0 2 2
2 0 2 2
1 1 3 4

解析:

1、当程序运行到defer函数时,不会执行函数实现,但会将defer函数中的参数代码进行执行。
因此首先执行的是calc("10", a, b)),随后执行的是calc("2", a, calc("20", a, b))
得到第一行和第二行结果。
2、defer的执行结果是先进后出,从函数尾部向函数头部以此执行。因此会首先执行calc("2", a, calc("20", a, b)),
然后执行defer calc("1", a, calc("10", a, b)),相应打印第三行和第四行

第7题

结果:

0 0 0 0 0 1 2 3

解析:

make([]int,5)的含义是创建数组,并且数组初始化5个元素,5个元素的值为类型零值。

第10题

结果:

编译不过去

解析:

原因是Student并没有继承People,people中有Speak(string)string方法,而Student类型中没有Speak()方法,
代码中的Student方法是*Student类型的,所有  var peo People = Student{}是不符合规范的。