Go語言學習查缺補漏ing Day6

恆生LIGHT雲社群發表於2021-12-09

作者: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被宣告瞭,可以使用=賦值。

第三條也正確,當多值賦值時,在:=左邊的變數如果有一個新變數,就能執行這條語句。如果:=左邊都是已經被宣告的變數,那麼這條語句也是錯誤的。

image-20211124133636559

第四條錯誤,b沒有被宣告。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70001864/viewspace-2846633/,如需轉載,請註明出處,否則將追究法律責任。

相關文章