写点什么

Go 语言学习查缺补漏 ing Day6

  • 2021 年 12 月 09 日
  • 本文字数:1312 字

    阅读完需:约 4 分钟

作者:ReganYue

来源:恒生LIGHT云社区

Go 语言学习查缺补漏 ing Day6

一、结构体嵌套时拥有同名方法的情况

我们来看一看下面这段代码代表的含义:


package main
import ( "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 main
import ( "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 main
import ( "fmt")
func main() { i := 888 defer func() { fmt.Println(i) }() i = i + 8888}
复制代码


这样输出结果就是 9776。


因为这样保存的副本是函数指针,所以值变化最终结果也会变化。

三、截取切片后的长度和容量问题

我们来看一看这段代码:


package main
import ( "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 条语句,哪条正确,哪条错误?


第一条是错误的,因为 a 已经被声明了,不能使用:=。


第二条正确,因为 a 被声明了,可以使用=赋值。


第三条也正确,当多值赋值时,在:=左边的变量如果有一个新变量,就能执行这条语句。如果:=左边都是已经被声明的变量,那么这条语句也是错误的。



第四条错误,b 没有被声明。

发布于: 22 小时前阅读数: 4
用户头像

还未添加个人签名 2018.11.07 加入

还未添加个人简介

评论

发布
暂无评论
Go语言学习查缺补漏ing Day6