91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Golang中的interface怎么使用

發布時間:2022-02-24 17:28:11 來源:億速云 閱讀:134 作者:iii 欄目:開發技術

這篇文章主要講解了“Golang中的interface怎么使用”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Golang中的interface怎么使用”吧!

萬能類型interface

Java以及其他語言當中接口是一種寫法規范,而在golang當中,interface其實也是一種值,它可以像是值一樣傳遞。并且在它的底層,它其實是一個值和類型的元組。

這里我們來看下golang官方文檔當中的一個例子:

package main


import (
 "fmt"
 "math"
)


type I interface {
 M()
}


type T struct {
 S string
}


func (t *T) M() {
 fmt.Println(t.S)
}


type F float64


func (f F) M() {
 fmt.Println(f)
}


func main() {
 var i I


 i = &T{"Hello"}
 describe(i)
 i.M()


 i = F(math.Pi)
 describe(i)
 i.M()
}


func describe(i I) {
 fmt.Printf("(%v, %T)\n", i, i)
}

在上面的代碼當中定義了一個叫做describe的方法,在這個方法當中我們輸出了兩個值,一個是接口i對應的值,另一個是接口i的類型。

可以看到接口當中既存儲了對應的結構體的實例的信息,也存儲了結構體的類型。因此interface可以理解成一種特殊的類型。

實際上也的確如此,我們可以把interface理解成一種萬能數據類型,它可以接收任何類型的值。我們看下下面這種用法:

var a1 interface{} = 1
var a2 interface{} = "abc"
list := make([]interface{}, 0)
list = append(list, a1)
list = append(list, a2)
fmt.Println(list)

在代碼當中我們創建了一個interface{}類型的slice,它可以接收任何類型的值和實例。另外我們用interface{}這個類型也可以接收任何結構體的值。這里可能會有些迷惑,其實很容易想明白。interface表示一種類型,可以接收任何實現了interface當中規定的方法的類型的值。當我們定義inteface{}的時候,其實是定義了空的interface,相當于不需要實現任何方法的空interface,所以任何類型都可以接收,這也就是它成為萬能類型的原因。

我們接收當然沒有問題,問題是我們怎么使用這些interface類型的值呢?

一種方法是我們可以判斷一個interface的變量類型。判斷的方法非常簡單,我們在interface的變量后面用.(type)的方法來判斷。它和mapkey值判斷一樣,會返回一個值和bool類型的標記。我們可以通過這個標記判斷這個類型是否正確。

if v, ok := a1.(int); ok {
    fmt.Println(v)
}

如果類型比較多的話使用switch也是可以的:

switch v := i.(type) {
case int:
    fmt.Println("int")
case string:
    fmt.Println("string")
}

空值nil

interface類型的空值是nil,和Python當中的None是一個意思,表示一個指針指向空。如果我們在Java或者是其他語言當中對一個空指針調用方法,那么會觸發NullPointerMethodError,也就是空指針報錯。這也是我們初學者在編程當中最容易遇到的錯誤,往往原因是忘記了對聲明進行初始化導致的。

但是在golang當中不會,即使是nil也可以調用interface的方法。舉個例子:

type T struct {
 S string
}


func (t *T) M() {
 fmt.Println(t.S)
}


func main() {
 var i I
 var t *T
 i = t
 i.M()
}

我們將t賦值給了i,問題是t并沒有進行初始化,所以它是一個nil,那么我們的i也就會是一個nil。我們對nil調用M方法,在M方法當中我們打印了t的局部變量S。由于t此刻是一個nil,它并沒有這個變量,所以會引發一個invalid memory address or nil pointer derefernce的錯誤,也就是對空指針進行尋址的錯誤。

要解決這個錯誤,其實很簡單,我們可以在M方法當中對t進行判斷,如果發現t是一個nil,那么我們則跳過執行的邏輯。當我們把M函數改成這樣之后,就不會觸發空指針的問題了。

func (t *T) M() {
    if t == nil {
        fmt.Println("nil")
        return
    }
 fmt.Println(t.S)
}

nil觸發異常的問題也是初學者經常遇到的問題之一,這也要求我們在實現結構體內方法的時候一定要記得判斷調用的對象是否為nil,避免不必要的問題。

賦值的類型選擇

我們都知道golang當中通過interface來實現多態,只要是實現了interface當中定義的函數,那么我們就可以將對應的實例賦值給這個interface類型。

這看起來沒有問題,但是在實際執行的時候仍然會有一點點小小的問題。比如說我們有這樣一段代碼:

type Integer int


type Operation interface {
 Less(b Integer) bool
 Add(b Integer)
}




func (a Integer) Less(b Integer) bool {
 return a < b
}


func (a *Integer) Add(b Integer) {
 *a += b
}

這段代碼非常簡單,我們定義了一個Operationinterface,并且實現了Integer類型的兩個方法。表面上看一切正常,但是有一個細節。LessAdd這兩個方法針對的類型是不同的,Less方法我們不需要修改原值,所以我們傳入的是Integer的值,而Add方法,我們需要修改原值, 所以我們傳入的類型是Integer的指針。

那么問題來了,這兩個方法的類型不同, 我們還可以將它的值賦值給Operation這個interface嗎?如果可以的話,我們應該傳遞的是值還是指針呢?下面代碼當中的第二行和第三行究竟哪個是正確的呢?

var a Integer = 1
var b Operation = &a
var b Operation = a

答案是第二行的是正確的,原因也很簡單,因為我們傳入指針之后,golang的編譯器會自動生成一個新的Less方法。在這個轉換了類型的方法當中去調用了原本的方法,相當于做了一層中轉。

func (a *Integer) Less(b Integer) bool{
    return (*a).Less(b)
}

那反過來行不行呢?我們也寫出代碼:

func (a Integer) Add (b Integer) {
    (&a).Add(b)
}

顯然這樣是不行的,因為函數執行之后修改的只能是Add這個方法當中a這個參數的值,而沒辦法修改原值。這和我們想要的不符合,所以golang沒有選擇這種策略。

感謝各位的閱讀,以上就是“Golang中的interface怎么使用”的內容了,經過本文的學習后,相信大家對Golang中的interface怎么使用這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

连州市| 合水县| 甘谷县| 苏尼特右旗| 大足县| 芜湖市| 乌拉特前旗| 兖州市| 内江市| 调兵山市| 板桥市| 德格县| 开化县| 和田县| 长治县| 荣成市| 开江县| 沿河| 新疆| 安福县| 丽江市| 察雅县| 小金县| 马关县| 璧山县| 巢湖市| 萍乡市| 保亭| 巧家县| 都昌县| 武川县| 黎平县| 广德县| 南投市| 望城县| 延寿县| 蚌埠市| 同心县| 东港市| 桑植县| 昂仁县|