100道GO笔试_答案&解析&扩展_选择题1-10
注释:
- 本文中出现的所有题目均来自于网络
- 本人只是对其进行解答和注释
- 所有题目均为个人解答方案,如有纰漏或更好的解答欢迎指正
选择题1-10:
- 下面属于关键字的是:
A. func
B. def
C. struct
D. class
[答案]:AC
[解析&扩展]:
- func用于定义函数,故A正确。
- def是python中的函数定义关键字,在GO中无此关键字,故B错误。
- struct用于定义结构体,故C正确
- class是大部分面向对象语言都会有的关键字,但是GO没有,所以D错误。
GO的常见关键字如下:
var, const, type, package, func, return, defer, go, select, interface, struct, chan, map, range, break, case, countinue, for, fallthrough, if, else, switch, goto, default
- 定义一个包内全局字符串变量,下面语法正确的是:
A. var str string
B. str := ""
C. str = ""
D. var str = ""
[答案]:AD
[解析&扩展]:
golang中变量定义和初始化有三种方式:
var i int = 100 // 最普通的定义方式
var i = 100 // 会自动推导类型,但是使用极少,就算不记得问题也不大,因为基本都会使用下面一种
var i := 100 // 自动推导类型,但是只能用于定义局部变量
- 通过指针变量 p 访问其成员变量 name,下面语法正确的是:
A. p.name
B. (*p).name
C. (&p).name
D. p->name
[答案]:AB
[解析&扩展]:
B的写法是最正确的,但是golang通过语法糖的方式让我们直接用A的写法也是可以的。因此AB正确。
C是对指针变量取地址,也就是对地址取地址,并没有这种操作--就像是给户口本办理户口本--属于户口本的户口本。
D中是C++的操作。
- 关于接口和类的说法,下面说法正确的是:
A. 一个类只需要实现了接口要求的所有函数,我们就说这个类实现了该接口
B. 实现类的时候,只需要关心自己应该提供哪些方法,不用再纠结接口需要拆得多细才合理
C. 类实现接口时,需要导入接口所在的包
D. 接口由使用方按自身需求来定义,使用方无需关心是否有其他模块定义过类似的接口
[答案]:ABD
[解析&扩展]:
- 关于字符串连接,下面语法正确的是:
A. str := 'abc' + '123'
B. str := "abc" + "123"
C. str := '123' + "abc"
D. fmt.Sprintf("abc%d", 123)
[答案]:BD
[解析&扩展]:
A: 单引号内只能是单个字符,故错误
B: +是最常见的拼接操作,故正确。
C: 同A。
D: 查看函数文档即可。
- 关于协程,下面说法正确是:
A. 协程和线程都可以实现程序的并发执行
B. 线程比协程更轻量级
C. 协程不存在死锁问题
D. 通过 channel 来进行协程间的通信
[答案]:AD
[解析&扩展]:
A:协程可以看作是线程的线程,因此也是可以完成并发操作的,故正确。
B: 一个线程可以拥有多个协程,所以B错误。
C: 任何读写操作都是存在死锁问题的。
D: 通信方式。
- 关于 init 函数,下面说法正确的是
2
A. 一个包中,可以包含多个 init 函数
B. 程序编译时,先执行导入包的 init 函数,再执行本包内的 init 函数
C. main 包中,不能有 init 函数
D. init 函数可以被其他函数调用
[答案]:
[解析&扩展]:
init函数的特点:
- 先于main函数执行,且不可被调用(D选项错误)。
- 没有参数和返回值。
- 每个包可以有多个init。(答案A正确,“每个包”也包含“main包”,所以C错误)
- 包的每个源文件(.go文件)可以有多个init函数(也验证了第3点)。
- golang无明确定义同一个包下的init执行顺序。
- 被依赖的包的init会被优先被导入。(答案B正确)
init函数的主要作用:
- 初始化不能采用初始化表达式初始化的变量--初始化比较复杂,不能在声明的时候初始化的变量,比如初始化一个2-100所有偶数的数组。
- 程序运行前的注册。
- 实现syn.Once功能。
- ......
匿名导入:
当你并不需要使用到这个包中的其他内容,只需要执行其init函数的时候可以使用匿名导入,即在导入包前面加一个下划线 "_"。比较常见的如数据库驱动的导入。
- 关于循环语句,下面说法正确的有:
A. 循环语句既支持 for 关键字,也支持 while 和 do-while
B. 关键字 for 的基本使用方法与 C/C++中没有任何差异
C. for 循环支持 continue 和 break 来控制循环,但是它提供了一个更高级的 break,可以选择中断哪
一个循环
D. for 循环不支持以逗号为间隔的多个赋值语句,必须使用平行赋值的方式来初始化多个变量
[答案]:CD
[解析&扩展]:
A:go中只有for一个循环语句--如果你要用goto实现循环我也不反对--但是可以通过for的不同写法完成while语句一样的效果,所以A错误
B: 最直白的就是go中的for循环不需要括号,所以A错误。
C: 可以通过标签的方式跳出到指定的循环,有点类似于shell的标签。所以C正确。
D: for循环允许一次初始化多个变量,但是不允许依次初始化多个变量,所以D正确。(举例: 可以使用for i,j := 0,0; i < 10; i++
但是不能使用for i:= 0, j := 0; i <10; i++
)
- 对于函数定义:
func add(args ...int) int {
sum := 0
for _, arg := range args {
sum += arg
}
return sum
}
下面对 add 函数调用正确的是:
A. add(1, 2)
B. add(1, 3, 7)
C. add([]int{1, 2})
D. add([]int{1, 3, 7}...)
[答案]:ABD
[解析&扩展]:
在形参中的三个点表示不定参数--不确定有多少个参数。所以你可以传递任意多个该类型的参数。因此AB正确。
可是在传递切片的时候需要将其打散之后传递--因为切片虽然包含多个元素,但是其本身只是一个元素,因此需要将其打散为一个一个的单独元素。打散方式就是在实参后面加三个点,所以C错误,D正确。
- 关于类型转化,下面语法正确的是:
A.
type MyInt int
var i int = 1
var jMyInt = i
B.
type MyIntint
var i int= 1
var jMyInt = (MyInt)i
C.
type MyIntint
var i int= 1
var jMyInt = MyInt(i)
D.
type MyIntint
var i int= 1
var jMyInt = i.(MyInt)
[答案]:C
[解析&扩展]:
A: go不支持隐式转换,必须使用显式转换,因此A错误。
B: 类型转换的方式为(type)value,所以B正确。
C: 这是python之类的类型转换方式,在golang中并没有,因此错误。
D:这是进行类型断言,即判断其是不是该类型,并不能起到类型转换的效果,因此错误