> 文章列表 > Go语言面试题--基础语法(26)

Go语言面试题--基础语法(26)

Go语言面试题--基础语法(26)

文章目录

    • 1.下面这段代码能否正常结束?
    • 2.下面这段代码输出什么?为什么?
    • 3.下面代码是否能编译通过?如果通过,输出什么?

1.下面这段代码能否正常结束?

func main() {v := []int{1, 2, 3}for i := range v {v = append(v, i)}
}

参考答案及解析:不会出现死循环,能正常结束。 循环次数在循环开始前就已经确定,循环内改变切片的长度,不影响循环次数。

2.下面这段代码输出什么?为什么?

func main() {var m = [...]int{1, 2, 3}for i, v := range m {go func() {fmt.Println(i, v)}()}time.Sleep(time.Second * 3)
}

for range 使用短变量声明(:=)的形式迭代变量,需要注意的是,变量 i、v 在每次循环体中都会被重用,而不是重新声明。

各个 goroutine 中输出的 i、v 值都是 for range 循环结束后的 i、v 最终值,而不是各个goroutine启动时的i, v值。可以理解为闭包引用,使用的是上下文环境的值。

两种可行的 fix 方法:
1.使用函数传递

for i, v := range m {go func(i,v int) {fmt.Println(i, v)}(i,v)
}

2.使用临时变量保留当前值

for i, v := range m {i := i           // 这里的 := 会重新声明变量,而不是重用v := vgo func() {fmt.Println(i, v)}()
}

3.下面代码是否能编译通过?如果通过,输出什么?

func Foo(x interface{}) {if x == nil {fmt.Println("empty interface")return}fmt.Println("non-empty interface")
}
func main() {var x *int = nilFoo(x)
}

参考答案及解析:non-empty interface 考点:interface 的内部结构,我们知道接口除了有静态类型,还有动态类型和动态值,当且仅当动态值和动态类型都为 nil 时,接口类型值才为 nil。这里的 x 的动态类型是 *int,所以 x 不为 nil。
4.下面代码输出什么?

func main() {ch := make(chan int, 100)// Ago func() {              for i := 0; i < 10; i++ {ch <- i}}()// Bgo func() {for {a, ok := <-chif !ok {fmt.Println("close")return}fmt.Println("a: ", a)}}()close(ch)fmt.Println("ok")time.Sleep(time.Second * 10)
}

参考答案及解析:程序抛异常。先定义下,第一个协程为 A 协程,第二个协程为 B 协程;当 A 协程还没起时,主协程已经将 channel
关闭了,当 A 协程往关闭的 channel 发送数据时会 panic,panic: send on closed channel。