Golang-array & slice

考点: go闭包

面试题: 下面的代码会输出什么,并说明原因

func Test_Closure_In_Func(t *testing.T) {
	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()
}

参考答案

多个goroutine的执行是无序的,所以本题的输出将会是无序的。
但由于闭包的特性,在所有A相关的goroutine中,i是for循环的一个外部变量,i的地址不变,其值随遍历的进行而改变,最终i=10;所以,所有A相关的goroutine将会输出A:10;
在所有B相关的goroutine中,i是函数参数,在函数传入参数的过程中会发生值拷贝,所以i指向每一个具体遍历的值;所以,所有B相关的goroutine将会输出B:i

参考文档

Golang面试题解析 3. 下面的代码会输出什么,并说明原因

考点: slice遍历时错误的获取子元素的方式

面试题: 以下代码有什么问题,说明原因

package main
import (
    "fmt"
)
type student struct {
    Name string
    Age  int
}
func pase_student() map[string]*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
    }
    return m
}
func main() {
    students := pase_student()
    for k, v := range students {
        fmt.Printf("key=%s,value=%v \n", k, v)
    }
}

测试: slice遍历时错误的获取子元素的方式

理论依据: 遍历slice时,不可以使用&stu的方式获取slice中的子元素
&stu表示获取stu这个变量的地址,而该变量的地址表示指向stus[i]的地址,故而该变量的地址会随着遍历过程的进行而改变
该变量的地址在初始化时指向stus[0]的地址; 随着遍历过程的进行,该变量的地址会被修改为stus[i]的地址;最终该变量的地址会修改为stus[len - 1]的地址;
所以通过&stu获取的将会是stus中最后一个子元素的地址
整个遍历过程中,stu变量的变化可理解为如下过程:

var stu student 
for _, stu = range stus {
    m[stu.Name] = &stu
}

代码验证: get_slice_element_wrong_test.go Test_Get_Slice_Element_Wrong_Validation

测试: slice遍历时正确的获取子元素的方式

理论依据: 正确的获取slice中子元素的方式应该是,先根据下标获取对应的子元素,再获取对应子元素的地址,根据地址定位实际的子元素并使用。
上述过程可以理解为如下代码:

for i, _ := range stus {
	// 根据下标定位子元素
	stu := stus[i]
	// 根据地址获取子元素的实际信息
	m[stu.Name] = &stu
}

代码验证: get_slice_element_wrong_test.go Test_Get_Slice_Element_Correct

参考文档

Golang经典面试题上 2. 以下代码有什么问题,说明原因

考点: slice的append

面试题: 请写出以下输入内容

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

golang 面试题 10、以下代码能编译过去吗?为什么?

相关知识点

数组的声明

// var: 用于声明变量的关键字
// chessMap: 数组名
// [11][11]int: 数组的容量(必须显式声明)及类型
var chessMap [11][11]int

参考文档

golang slice/map/chan的初始化
【Golang】去除slice中重复的元素,认识空struct

你可能感兴趣的:(Golang)