开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第32天,点击查看活动详情
今天来学习下Go常见的习题问题(九),也是面试中可能会遇到的,让我们来一起学习吧~
结构体指针
观察下列代码,判断输出结果是什么?
type People interface {
Speak(string) string
}
type Student struct{}
func (stu *Student) Speak(think string) (talk string) {
if think == "speak" {
talk = "qqyy"
} else {
talk = "yyqq"
}
return
}
func main() {
var peo People = Student{}
think := "speak"
fmt.Println(peo.Speak(think))
}
参考答案:上述代码不能通过编译,错误类型如下图所示,因为值类型Student没有实现接口的Speak()方法,而指针类型*Student实现了该方法,所以需要修改的地方是 var peo People = &Student{}加上取地址符号即可
iota输出
观察下列代码,分析输出的结果?
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是go语言中的常量计数器,只能在常量的表达式中使用,用const包围的常量表达式中,每增加一行会使iota计数加一,遇到新的const常量表达式会重置为0
接口类型比较
观察下列代码,判断输出结果是什么?为什么?
type People interface {
Show()
}
type Student struct{}
func (stu *Student) Show() {
}
func main() {
var s *Student
if s == nil {
fmt.Println("s is nil")
} else {
fmt.Println("s is not nil")
}
var p People = s
if p == nil {
fmt.Println("p is nil")
} else {
fmt.Println("p is not nil")
}
}
参考答案:输出s is nil和 p is not nil,第一个输出为nil很好理解,只是声明了指针类型的结构体,没有分配内存地址,第二个将s赋值给一个接口类型,当且仅当动态值和动态类型值都为nil的时候,接口类型才会判定成nil,赋值给p之后,p的动态值为nil,但是动态类型的值为*Student是一个nil指针,不符合判定条件,所以输出结果为 p is not nil
:=操作符
观察下列代码,判断输出结果?为什么?
var p *int
func foo() (*int, error) {
var i int = 5
return &i, nil
}
func bar() {
fmt.Println(*p) //这里是使用全局变量p
}
func main() {
p, err := foo()
if err != nil {
fmt.Println(err)
return
}
bar()
fmt.Println(*p)
}
参考答案:运行时错误,因为在使用:=定义的变量的时候,如果出现与同名定义的变量不在一个作用域中的时候,会重新定义这个变量,而不是用全局定义的那个变量,所以在本例题中,局部的变量p遮挡住了全局的变量P,这就导致运行到bar()程序的时候,全局变量p的值为nil,就会导致程序奔溃,正确的修改应该是赋值语句修改下:
func main() {
var err error
p, err = foo()
if err != nil {
fmt.Println(err)
return
}
bar()
fmt.Println(*p)
}
总结
今天浅谈了Go的习题(九),主要介绍了GO面试中会出现的问题,接下来会继续分享其他的习题的相关知识,对于一个刚入门的我来说,还有许多地方需要学习,有错误的地方欢迎大家指出,共同进步!!