61-90
61. 下面这段代码输出什么?
const (
a = iota
b = iota
)
const (
name = "name"
c = iota
d = iota
)
func main() {
fmt.Println(a)
fmt.Println(b)
fmt.Println(c)
fmt.Println(d)
}答:0 1 1 2
解析:
知识点:iota 的用法。
iota 是 golang 语言的常量计数器,只能在常量的表达式中使用。
iota 在 const 关键字出现时将被重置为0,const中每新增一行常量声明将使 iota 计数一次。
62. 下面这段代码输出什么?为什么?
答:s is nil 和 p is not nil
解析:
这道题会不会有点诧异,我们分配给变量 p 的值明明是 nil,然而 p 却不是 nil。记住一点,当且仅当动态值和动态类型都为 nil 时,接口类型值才为 nil。上面的代码,给变量 p 赋值之后,p 的动态值是 nil,但是动态类型却是 *Student,是一个 nil 指针,所以相等条件不成立。
63. 下面这段代码输出什么?
答:South
解析:
知识点:iota 的用法、类型的 String() 方法。
64. 下面代码输出什么?
A. 4
B. compilation error
答:B
解析:
编译报错 cannot assign to struct field m["foo"].x in map。错误原因:对于类似 X = Y的赋值操作,必须知道 X 的地址,才能够将 Y 的值赋给 X,但 go 中的 map 的 value 本身是不可寻址的。
有两个解决办法:
使用临时变量
修改数据结构
65. 下面的代码有什么问题?
答:有两处错误
解析:
go 中不同类型是不能比较的,而数组长度是数组类型的一部分,所以
[…]int{1}和[2]int{1}是两种不同的类型,不能比较;切片是不能比较的;
66. 下面这段代码输出什么?如果编译错误的话,为什么?
A. 5 5
B. runtime error
答:B
解析:
知识点:变量作用域。
问题出在操作符:=,对于使用:=定义的变量,如果新变量与同名已定义的变量不在同一个作用域中,那么 Go 会新定义这个变量。对于本例来说,main() 函数里的 p 是新定义的变量,会遮住全局变量 p,导致执行到bar()时程序,全局变量 p 依然还是 nil,程序随即 Crash。
正确的做法是将 main() 函数修改为:
67. 下面这段代码能否正常结束?
答:不会出现死循环,能正常结束
解析:
循环次数在循环开始前就已经确定,循环内改变切片的长度,不影响循环次数。
68. 下面这段代码输出什么?为什么?
答:
解析:
for range 使用短变量声明(:=)的形式迭代变量,需要注意的是,变量 i、v 在每次循环体中都会被重用,而不是重新声明。
各个 goroutine 中输出的 i、v 值都是 for range 循环结束后的 i、v 最终值,而不是各个goroutine启动时的i, v值。可以理解为闭包引用,使用的是上下文环境的值。
两种可行的 fix 方法:
使用函数传递
使用临时变量保留当前值
69. 下面这段代码输出什么?
答:7
解析:
第一步执行r = n +1,接着执行第二个 defer,由于此时 f() 未定义,引发异常,随即执行第一个 defer,异常被 recover(),程序正常执行,最后 return。
70. 下面这段代码输出什么?
答:
解析:
range 表达式是副本参与循环,就是说例子中参与循环的是 a 的副本,而不是真正的 a。就这个例子来说,假设 b 是 a 的副本,则 range 循环代码是这样的:
因此无论 a 被如何修改,其副本 b 依旧保持原值,并且参与循环的是 b,因此 v 从 b 中取出的仍旧是 a 的原值,而非修改后的值。
如果想要 r 和 a 一样输出,修复办法:
输出:
修复代码中,使用 *[5]int 作为 range 表达式,其副本依旧是一个指向原数组 a 的指针,因此后续所有循环中均是 &a 指向的原数组亲自参与的,因此 v 能从 &a 指向的原数组中取出 a 修改后的值。
71. 下面这段代码输出什么?
答:
解析:
知识点:可变函数、append()操作。
Go 提供的语法糖...,可以将 slice 传进可变函数,不会创建新的切片。第一次调用 change() 时,append() 操作使切片底层数组发生了扩容,原 slice 的底层数组不会改变;第二次调用change() 函数时,使用了操作符[i,j]获得一个新的切片,假定为 slice1,它的底层数组和原切片底层数组是重合的,不过 slice1 的长度、容量分别是 2、5,所以在 change() 函数中对 slice1 底层数组的修改会影响到原切片。
72. 下面这段代码输出什么?
答:
解析:
切片在 go 的内部结构有一个指向底层数组的指针,当 range 表达式发生复制时,副本的指针依旧指向原底层数组,所以对切片的修改都会反应到底层数组上,所以通过 v 可以获得修改后的数组元素。
73. 下面这段代码输出结果正确正确吗?
答:s2 的输出结果错误
解析:
s2 的输出是 &{C} &{C} &{C},for range 使用短变量声明(:=)的形式迭代变量时,变量 i、value 在每次循环体中都会被重用,而不是重新声明。所以 s2 每次填充的都是临时变量 value 的地址,而在最后一次循环中,value 被赋值为{c}。因此,s2 输出的时候显示出了三个 &{c}。
可行的解决办法如下:
74. 下面代码里的 counter 的输出值?
A. 2
B. 3
C. 2 或 3
答:C
解析:
for range map 是无序的,如果第一次循环到 A,则输出 3;否则输出 2。
75. 关于协程,下面说法正确是()
A. 协程和线程都可以实现程序的并发执行;
B. 线程比协程更轻量级;
C. 协程不存在死锁问题;
D. 通过 channel 来进行协程间的通信;
答:A D
76. 关于循环语句,下面说法正确的有()
A. 循环语句既支持 for 关键字,也支持 while 和 do-while;
B. 关键字 for 的基本使用方法与 C/C++ 中没有任何差异;
C. for 循环支持 continue 和 break 来控制循环,但是它提供了一个更高级的 break,可以选择中断哪一个循环;
D. for 循环不支持以逗号为间隔的多个赋值语句,必须使用平行赋值的方式来初始化多个变量;
答:C D
77. 下面代码输出正确的是?
A. s: [Z,B,C]
B. s: [A,Z,C]
答:A
解析:
知识点:多重赋值。
多重赋值分为两个步骤,有先后顺序:
计算等号左边的索引表达式和取址表达式,接着计算等号右边的表达式;
赋值;
所以本例,会先计算 s[i-1],等号右边是两个表达式是常量,所以赋值运算等同于 i, s[0] = 2, "Z"。
78. 关于类型转化,下面选项正确的是?
答:C
解析:
知识点:强制类型转化
79. 关于switch语句,下面说法正确的有?
A. 条件表达式必须为常量或者整数;
B. 单个case中,可以出现多个结果选项;
C. 需要用break来明确退出一个case;
D. 只有在case中明确添加fallthrough关键字,才会继续执行紧跟的下一个case;
答:B D
80. 如果 Add() 函数的调用代码为:
则Add函数定义正确的是()
答:A C
解析:
知识点:类型断言、方法集。
81. 关于 bool 变量 b 的赋值,下面错误的用法是?
A. b = true
B. b = 1
C. b = bool(1)
D. b = (1 == 2)
答:B C
82. 关于变量的自增和自减操作,下面语句正确的是?
答:A D
解析:
知识点:自增自减操作。
i++ 和 i-- 在 Go 语言中是语句,不是表达式,因此不能赋值给另外的变量。此外没有 ++i 和 --i。
83. 关于GetPodAction定义,下面赋值正确的是
A. var fragment Fragment = new(GetPodAction)
B. var fragment Fragment = GetPodAction
C. var fragment Fragment = &GetPodAction{}
D. var fragment Fragment = GetPodAction{}
答:A C D
84. 关于函数声明,下面语法正确的是?
A. func f(a, b int) (value int, err error)
B. func f(a int, b int) (value int, err error)
C. func f(a, b int) (value int, error)
D. func f(a int, b int) (int, int, error)
答:A B D
85. 关于整型切片的初始化,下面正确的是?
A. s := make([]int)
B. s := make([]int, 0)
C. s := make([]int, 5, 10)
D. s := []int{1, 2, 3, 4, 5}
答:B C D
86. 下面代码会触发异常吗?请说明。
解析:
select 会随机选择一个可用通道做收发操作,所以可能触发异常,也可能不会。
87. 关于channel的特性,下面说法正确的是?
A. 给一个 nil channel 发送数据,造成永远阻塞
B. 从一个 nil channel 接收数据,造成永远阻塞
C. 给一个已经关闭的 channel 发送数据,引起 panic
D. 从一个已经关闭的 channel 接收数据,如果缓冲区中为空,则返回一个零值
答:A B C D
88. 下面代码有什么问题?
答:编译报错
解析:
编译报错cannot take the address of i。知识点:常量。常量不同于变量的在运行期分配内存,常量通常会被编译器在预处理阶段直接展开,作为指令数据使用,所以常量无法寻址。
89. 下面代码能否编译通过?如果通过,输出什么?
答:不能通过编译
解析:
知识点:函数返回值类型。nil 可以用作 interface、function、pointer、map、slice 和 channel 的“空值”。但是如果不特别指定的话,Go 语言不能识别类型,所以会报错:cannot use nil as type string in return argument
90. 关于异常的触发,下面说法正确的是?
A. 空指针解析;
B. 下标越界;
C. 除数为0;
D. 调用panic函数;
答:A B C D
最后更新于