關於 interface{} 會有啥注意事項?下

阿兵雲原生發表於2023-03-13

我們一起來回顧一下上一次說到的 interface{}

  • 可以用來做多型
  • 介面型別分為空介面型別和非空介面型別,他們的底層資料結構不太一樣

這裡順便說一下,用來作態需要滿足這樣的條件:

  • 首先得有父類指標指向子類的物件
  • 這個介面還必須是非空介面,裡面得包含方法,也就是使用的底層資料結構是 iface
  • 子類會去實現父類的具體方法

interface{} 注意斷言

正常的使用斷言,寫一個簡單的 斷言 demo

type Animal interface{}

func main() {
    var a Animal = "xiaomotong"
    v, ok := a.(string)
    if !ok{
        fmt.Println("type error")
    }
    fmt.Println("v == ",v)
}

斷言注意寫成 2 個返回值的,一個是具體的值,一個是 bool,判斷斷言是否成功,若成功則說明斷言正確,且 v 會被賦值為實際變數的值

切忌沒頭腦的強轉

func main() {
    var a Animal = "xiaomotong"

    v := a.(int)
    fmt.Println("v == ",v)
}

上述這種寫法,若不判斷是否斷言成功,直接強轉,程式是會 panic 的 ,執行上述程式後效果如下:

>go run main.go
panic: interface conversion: main.Animal is string, not int

goroutine 1 [running]:
main.main()
        D:/mycode/my_new_first/interface_test/main.go:13 +0x4c
exit status 2

程式崩掉,那就是線上問題了 xdm ,這裡需要注意

當然我們也可以這樣寫

type Animal interface{}

func main() {
    var a Animal = "xiaomotong"

    switch a.(type) {

    case string:
        fmt.Println("a type is string")
    case int:
        fmt.Println("a type is int")
    }

}

透過 switch 的方式來判斷 介面的資料型別,根據不同的資料型別來做不同的事情,進行分類處理

用於反射的注意點

golang 裡面有反射這個概念,簡單來說,我們們可以透過反射包來實現獲取介面真實的型別,和真實的資料

舉個小例子:

透過反射來獲取 Animal 介面的資料型別,和具體的資料值

type Animal interface{}

func main() {
    var a Animal = "xiaomotong"
    v := reflect.ValueOf(a)
    fmt.Printf("v type == ", v.Type(), " v == ", v.String())
}

執行上述程式碼後效果如下:

> go run main.go
v type == %!(EXTRA *reflect.rtype=string, string= v == , string=xiaomotong)

沒毛病正常獲取,但是如果我們這樣寫的話是不是也可以正確執行呢?

type Animal interface{}

func main() {
    var a Animal = "xiaomotong"
    v := reflect.ValueOf(a)
    fmt.Printf("v type == ", v.Type(), " v == ", v.Int())
}

看這個例子也就和上面的例子相差在輸出的時候,一個是v.String() ,一個是v.Int() ,可是結果卻相差很大

go run main.go
v type == %!(EXTRA *reflect.rtype=string, string= v == , string=xiaomotong)
D:\mycode\my_new_first\interface_test>go run main.go
panic: reflect: call of reflect.Value.Int on string Value

goroutine 1 [running]:
reflect.Value.Int(...)
        C:/Program Files/Go/src/reflect/value.go:999
main.main()
        D:/mycode/my_new_first/interface_test/main.go:26 +0x2bd
exit status 2

執行上述程式碼,go 程式給我們報了 panic 錯誤,這裡需要注意 ,程式崩潰的原因是,我們將一個 string 型別的值反射成一個 Int 型別的值,直接在 反射包裡面就給我們報了 panic

小知識,大挑戰,簡單的寫 2 個注意事項,給 xdm 提個醒

歡迎點贊,關注,收藏

朋友們,你的支援和鼓勵,是我堅持分享,提高質量的動力

好了,本次就到這裡

技術是開放的,我們的心態,更應是開放的。擁抱變化,向陽而生,努力向前行。

我是阿兵雲原生,歡迎點贊關注收藏,下次見~

相關文章