作者:ReganYueGo语言学习查缺补漏ing Day6
来源:恒生LIGHT云社区
一、结构体嵌套时拥有同名方法的情况 我们来看一看下面这段代码代表的含义:
package mainimport (
"fmt"
)type Student struct{}func (s *Student) sayHello() {
fmt.Println("sayHello")
s.sayBey()
}
func (s *Student) sayBey() {
fmt.Println("sayBey")
}type Teacher struct {
Student
}func (t *Teacher) sayBey() {
fmt.Println("teacher sayBey")
}
func main() {
t := Teacher{}
t.sayBey()
}
在这里面有一个嵌套结构体,其中Teacher是外部类型,Student是内部类型。这样就能实现内部属性,也就是这的Student的属性方法,能够被外部类型也就是Teacher拥有。当然,外部属性也可以拥有自己的属性、方法,如果拥有了与内部类型一样名字的方法,那么同名的内部类型的方法就会失去作用。
这个例子的输出结果是什么,我想你应该知道了:
teacher sayBey
这个例子中的sayBey()方法就是同名的方法,所以内部类型Student的这个方法会失去作用,调用就是调用Teacher中定义的sayBey()方法。
二、使用defer执行函数的一个注意事项
package mainimport (
"fmt"
)func sayHello(i int) {
fmt.Println(i)
}
func main() {
i := 888
defer sayHello(i)
i = i + 8888
}
我们都知道defer是在最后执行的,那么你看一看这里输出什么?
答案是:888
为什么呢?
因为程序在运行到
defer sayHello(i)
时就把函数中的参数的副本保存,这里保存的参数i的值就为888.因此,sayHello(i)的结果并不是在主函数结束之前进行,而是在
defer
关键字调用时计算的。怎么解决这个问题呢?
很简单,在defer时使用匿名函数就行了。
package mainimport (
"fmt"
)func main() {
i := 888
defer func() { fmt.Println(i) }()
i = i + 8888
}
这样输出结果就是9776。
因为这样保存的副本是函数指针,所以值变化最终结果也会变化。
三、截取切片后的长度和容量问题 我们来看一看这段代码:
package mainimport (
"fmt"
)func main() {
s := []int{0, 0, 0}
a := s[:0]
b := s[:2]
c := s[1:2:cap(s)]fmt.Println(len(a), cap(a))
fmt.Println(len(b), cap(b))
fmt.Println(len(c), cap(c))
}
你觉得运行结果是什么?
回答这个问题需要了解截取操作,截取操作一般是两个参数,代表截取的起始位置和终止位置,截取的部分不包括第二个参数。而第三个参数就是更改切片的容量,但是第三个参数不能大于切片底层数组的长度。如果第一个参数省略,那代表第一个参数为0,如果第二个参数省略了,那么代表第二个参数为这个切片底层数组的长度。
四、变量声明的一个小知识
1. a, _ := f()
2. a, _ = f()
3. a, b := f()
4. a, b = f()
假如这段代码之前a已经被声明了,而b还没有被声明。那么上面4条语句,哪条正确,哪条错误?
【Go语言学习查缺补漏ing Day6】第一条是错误的,因为a已经被声明了,不能使用:=。
第二条正确,因为a被声明了,可以使用=赋值。
第三条也正确,当多值赋值时,在:=左边的变量如果有一个新变量,就能执行这条语句。如果:=左边都是已经被声明的变量,那么这条语句也是错误的。
文章图片
第四条错误,b没有被声明。