开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第31天,点击查看活动详情
今天来学习下Go常见的习题问题(八),也是面试中可能会遇到的,让我们来一起学习吧~
nil切片和空切片
观察下列两个切片的声明方式,有什么区别?
1. var w []int
2. w := []int{}
参考答案:第一个声明的形式是nil切片,第二个声明的形式是长度和容量都为0的空切片,第一个声明的方式不会被分配内存,优先选择
inerface{}类型
观察下列代码,是否可以通过编译?不可以的话,说明理由
type YYQQ struct {
}
func f(x interface{}) {
}
func g(x *interface{}) {
}
func main() {
s := YYQQ{}
p := &s
f(s)
g(s)
f(p)
g(p)
}
参考答案:不能通过编译,g(s) g(p)不能通过编译,因为g函数定义的是*interface{}类型的指针,如果参数是interface{}是可以接收任意类型的参数,包括用户自定义的类型,就算是指针类型也可以用interface{}接收,这里需要注意的是,不要将一个指针指向一个接口类型,因为它本身就是一个指针
指针类型
观察下列代码,划线部分应该填入什么,才可以保证输出结果为YYQQ
type S struct {
m string
}
func f() *S {
return __ //A
}
func main() {
p := __ //B
fmt.Println(p.m) //print "YYQQ"
}
参考答案:A处应该填入&S{"YYQQ"},B处应该填入*f()或者f(),因为f()函数返回的值结构体S的指针类型,所以要用取地址符&取结构体的指针,第二处如果填*f()取到的是S类型,如果填f()取到的是*P类型,但这两种都可以通过p.m取到结构体的成员
字符串赋值
观察下列代码,是否可以通过编译?如果可以,输出结果
package main
import (
"fmt"
)
func main() {
var x string = nil
if x == nil {
x = "YYQQ"
}
fmt.Println(x)
}
参考答案:不能通过编译,因为go语言中的string类型是不能赋值nil,也不能和nil进行比较
切片操作
观察下列代码,输出结果是什么?为什么?
func main() {
s1 := []int{1, 2, 3}
s2 := s1[1:]
s2[1] = 4
fmt.Println(s1)
s2 = append(s2, 5, 6, 7)
fmt.Println(s1)
}
参考答案:两次输出的结果都是[1 2 4],因为切片底层数据结构是数组,s2通过s1进行截取获得,和s1共享同一个底层数组,那么就会导致s2修改会影响s1的值,但是append操作会导致底层数组扩容,生成新的数组,所以后续追加的值不会影响s1,如果再修改s2也同样不会改变s1的值
map输出
观察下列代码,输出结果是什么?
func main() {
m := map[int]string{0:"zero",1:"one"}
for k,v := range m {
fmt.Println(k,v)
}
}
参考答案:
0 zero
1 one
// 或者
1 one
0 zero
因为map是无序输出,受到无序写入和扩容的影响,正常写入:虽然buckets是一块连续的内存,但是每次写入都会通过hash到记录到某一个bucket上,而不是按buckets顺序写入, 哈希冲突写入:如果存在hash冲突,会写到同一个bucket上,导致数据的错误,map扩容有两种成倍扩容和等量扩容
总结
今天浅谈了Go的习题(八),主要介绍了GO面试中会出现的问题,接下来会继续分享其他的习题的相关知识,对于一个刚入门的我来说,还有许多地方需要学习,有错误的地方欢迎大家指出,共同进步!!