希望每一个正在准备golang面试的小伙伴可以看到这篇文章,找到满意的工作!

今天给大家分享一个关于120天Golang面试题相关的文章,这些题目包含很多Go语言易错点、常见的坑和值得关注的点,认真追完这一系列的同学都说收获非常大!说实话,其实这不仅仅是一份面试题,还是一份可以拿来查漏补缺的Go语言参考资料

全文总共有263道题,这些题目大部分参考了网上优秀的资料,比如Go语言中文网、http://tonybai.com、《Go语言101》 等,参考的资料太多,就不一一列举了,题目后面也有出处以及相关的阅读资料。

部分内容如下:

第 1 天

1.下面这段代码输出的内容

答案:

解析:defer 的执行顺序是后进先出。当出现 panic 语句的时候,会先按照 defer 的后进先出的顺序执行,最后才会执行panic。

第 2 天

1.下面这段代码输出什么,说明原因。

参考答案:

解析:这是新手常会犯的错误写法,for range循环的时候会创建每个元素的副本,而不是元素的引用,所以m[key] = &val取的都是变量val的地址,所以最后map中的所有元素的值都是变量val的地址,因为最后val被赋值为3,所有输出都是3.正确的写法:

扩展题目

第 3 天

1.下面两段代码输出什么。

2.下面这段代码有什么缺陷

答案:第二个返回值没有命名。

解析:在函数有多个返回值时,只要有一个返回值有命名,其他的也必须命名。如果有多个返回值必须加上括号();如果只有一个返回值且命名也必须加上括号()。这里的第一个返回值有命名sum,第二个没有命名,所以错误。

3.new()与make()的区别。

new(T)和make(T,args)是Go语言内建函数,用来分配内存,但适用的类型不同。

new(T)会为T类型的新值分配已置零的内存空间,并返回地址(指针),即类型为*灯的值。换句话说就是,返回一个指针,该指针指向新分配的、类型为T的零值。适用于值类型,如数组、结构体等。

make(T,args)返回初始化之后的T类型的值,这个值并不是T类型的零值,也不是指针*T,是经过初始化之后的T的引用。make() 只适用于slice、map和channel.

第 4 天

1.下面这段代码能否通过编译,不能的话原因是什么;如果通过,输出什么。

参考答案:不能通过编译,new([]int) 之后的 list 是一个 *[]int 类型的指针,不能对指针执行 append 操作。可以使用⽤ make() 初始化之后再用。同样的,map 和 channel 建议使用 make() 或字面量的方式初始化,不要用 new() 。

2.下面这段代码能否通过编译,如果可以,输出什么?

参考答案:不能通过编译。append() 的第二个参数不能直接使⽤ slice,需使用 … 操作符,将一个切片追加到另一个切片上:append(s1,s2…)。或者直接跟上元素,形如:append(s1,1,2,3)。

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

参考答案:不能通过编译。

参考解析:这道题的主要知识点是变量声明的简短模式,形如: x:= 100.但这种声明方式有限制:

1.必须使用显示初始化;

2.不能提供数据类型,编译器会自动推导;

3.只能在函数内部使用简短模式;

5

1.下面这段代码能否通过编译?不能的话,原因是什么?如果通过,输出什么?

参考答案:编译不通过invalid operation: sm1 == sm2

参考解析:这道题目考的是结构体的比较:

1.结构体只能比较是否相等,但是不能比较大小。

2.相同类型的结构体才能够进行比较,结构体是否相同不但与属性类型有关,还与属性顺序相关,sn3与sn1就是不同的结构体;

3. 如果 struct 的所有成员都可以比较,则该 struct 就可以通过 == != 进行比较是否相等,比较时逐个项进行比较,如果每一项都相等,则两个结构体才相等,否则不相等;


第6天

1 .通过指针变量p访问其成员变量name, 有哪几种方式?

●A.p.name

●B.(&p).name

●C.(*p).name

●D.p->name

参考答案: AC参考解析: &取址运算符,*指针解引用。

2.下面这段代码能否通过编译?如果通过,输出什么?

参考答案:编译不通过,cannot use i (type int) as type MyInt1 in assignment


参考解析:这道题考的是类型别名与类型定义的区别。第5行代码是基于类型int创建了新类型MyInt1,第6行代码是创建了int的类型别名MyInt2,注意类型别名的定义时=。所以,第10行代码相当于是将int类型的变量赋值给MyInt1类型的变量,Go是强类型语言,编译当然不通过;而MyInt2只是int的别名,本质.上还是int,可以赋值。第10行代码的赋值可以使用强制类型转化var i1 MyInt1 = MyInt1(i).

第7天

1.关于字符串连接,下面语法正确的是?

●A.str:= 'abc' +'123'

●B.str := "abc"+ "123"

●C. str:= '123' + "abc"

●S. fmt. Sprintf("abc%d", 123)

参考答案: BD

参考解析:考的知识点是字符串连接。除了以上两种连接方式,还有strings.Join().buffer .WriteString()等。

2.下面这段代码能否编译通过?如果可以,输出什么?

参考答案:编译通过,输出:0 2 zz zz 5

3.下面赋值正确的是()

●A.varx= nil

●B. var x interface{}= nil

●C. var x string= nil

●D. var x error= nil

参考答案及解析: BD。

这道题考的知识点是nil。nil 只能赋值给指针、chan、 func、 interface、 map或slice类型的变量。强调下D选项的error类型,它是一-种内置接口类型,看它的源码就知道,所以D是对的。

第8天


1.关于init函数,下面说法正确的是()

●A.一个包中,可以包含多个init函数;

●B.程序编译时,先执行依赖包的init函数,再执行main包内的init函数; .

●C. main包中,不能有init函数;

●D. init函数可以被其他函数调用;

参考答案及解析: AB。


关于init()函数有几个需要注意的地方:

1. init() 函数是用于程序执行前做包的初始化的函数,比如初始化包里的变量等;

2. 一个包可以出线多个init()函数,一个源文件也可以包含多个init()函数;

3.同一个包中多个init()函数的执行顺序没有明确定义,但是不同包的init函数是根据包导入的依赖关系决定的;

4. init() 函数在代码中不能被显示调用、不能被引用(赋值给函数变量),否则出现编译错误;

5.一个包被引用多次,如A import B,C import B,A importC, B被引用多次,但B包只会初始化一次;

6.引入包,不可出现死循坏。即A import B,B import A,这种情况编译失败;


2.下面这段代码输出什么以及原因?

  • A. nil
  • B. not nil
  • C. compilation error

答案及解析:B。

这道题目里面,是将 hello() 赋值给变量 h,而不是函数的返回值,所以输出 not nil。

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

答案及解析:编译失败。考点:类型选择,类型选择的语法形如: i.(type), 其中i是接口,type 是固定关键字,需要注意的是,只有接口类型才可以使用类型选择。


第9天

1.关于channel,下面语法正确的是()

●A. var ch chan int

●B. ch := make(chan int)

●C.<-ch

●D.ch<-

参考答案及解析: ABC。A、B都是声明channel; C读取channel;写channel是必须带上值,所以D错误。

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

●A.0

●B.1

●C.Compilation error

参考答案及解析: A。打印一个map中不存在的值时,返回元素类型的零值。这个例子中,m的类型是map[person]int,因为m中不存在p,所以打印int类型的零值,即0。


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

●A.18

●B.5

●C.Compilation error

参考答案及解析:18。知识点:可变函数。


10

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

●A.13.1

●B.13

●C.compilation error

参考答案及解析: C。a的类型是int, b的类型是float,两个不同类型的数值不能相加,编译报错。


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

●A.3

●B.4

●C.compilation error

参考答案及解析: B。

知识点:操作符[ij]。基于数组(切片) 可以使用操作符[ij] 创建新的切片,从索引i,到索引j结束,截取已有数组(切片)的任意部分,返回新的切片,新切片的值包含原数组(切片) 的i索引的值,但是不包含j索引的值。i、 j都是可选的,i如果省略,默认是0,j 如果省略,默认是原数组(切片)的长度。i、j都不能超过这个长度值。

假如底层数组的大小为k,截取之后获得的切片的长度和容量的计算方法:长度: j-i,容量: k-i

截取操作符还可以有第三个参数,形如[ij,k],第三个参数k用来限制新切片的容量,但不能超过原数组(切片)的底层数组大小。截取获得的切片的长度和容量分别是: j-i、 k-i。所以例子中,切片t为[4],长度和容量都是1。

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

●A. compilation error

●B. equal

●C. not equal

参考答案及解析: A。Go中的数组是值类型,可比较,另外-方面,数组的长度也是数组类型的组成部分,所以a和b是不同的类型,是不能比较的,所以编译错误。

1.请点击下方窗口

2.(备注:Golang面试题120天)