中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

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

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

Go語言接口類型怎么定義

發布時間:2023-03-29 10:27:54 來源:億速云 閱讀:126 作者:iii 欄目:開發技術

今天小編給大家分享一下Go語言接口類型怎么定義的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。

接口

接口是用來定義行為的類型,定義的行為不由接口直接實現,而由通過方法由定義的類型實現

Golang中,接口是一組方法的簽名,是語言中一個重要的組成部分,其目的是通過引入一個中間層與具體的實現進行分離,達到解耦合的作用,同時隱藏底層實現,減少關注點

Golang不同于Java,通過隱式實現聲明的接口,即只要實現了接口聲明中的方法,就是實現了接口,
接口的定義需要使用interface關鍵字,且在接口中只能定義方法簽名,不能包含成員變量

基于官方的io包進行分析:

type Reader interface {
   Read(p []byte) (n int, err error)
}

上面是io包中聲明的Reader接口,如果一個類型需要實現Reader接口,那么就僅需要實現Read(p []byte) (n int, err error)方法,如LimitedReader就實現了Reader接口:

type LimitedReader struct {
    R Reader
    N int64
}

func(l *LimitedReader) Read(p []byte) (n int, err error) {
    if ;.N <= 0 {
        return 0, EOF
    }
    if int64(len(p)) > l.N {
        p = p[o:l.N]
    }
    n, err := l.R.Read(p)
    l.N -= int64(n)
    return
}

Golang只會在參數傳遞、返回參數和變量賦值時對類型是否實現了某個接口進行檢查,接口在定義方法時對實現的接受者做限制,所以會有兩種方式實現接口:結構體實現和指針實現。

但這兩種實現方式不可以同時存在,Go語言的編譯器會在結構體類型和指針類型都實現同一個方法時報錯“method redeclared”

type Cat struct {}
type Duck interface {}

func (c Cat) Quack {} // 結構體實現
func (c *Cat) Quack {} // 指針實現

var d Duck = Cat{} // 結構體初始化
var d Duck = &Cat{} // 指針初始化

注意:指針實現接口,結構體初始化變量是無法通過編譯的;而結構體實現接口,指針初始化變量可以

(Golang在傳遞參數是值傳遞的,指針初始化變量時,指針可以隱式地獲取到指向的結構體:c.i可以理解成(*c).i)

詳細理解就是在Golang中,初始化變量后進行方法調用時會發生`值拷貝`:

1.對于初始化的指針來說,意味著拷貝的新指針仍然與原指針一樣,指向一個相同且唯一的結構體,所以編譯器可以隱式通過對變量的解引用(dereference)獲取到指針的結構體

2.而對于結構體而言,這是拷貝生成了新的結構體,但方法的參數是指針,編譯器既不可能創建一個新的指針,即使創建也無法指向最初調用該方法的結構體
具體的例子如Goinaction的代碼示例:

listing36.go

package main

import (
    "fmt"
)

type notifier interface {
    notify()
}

type user struct {
    name string
    email string
}

func (u *user) notify() {
    fmt.Printf("Sending user email to %s<%s>)\n",
    u.name,
    u.email)
}

func main() {
    u := user{"Bill", "bill@email.com"}
    
    sendNotification(u)
}

func sendNotification(n notifier) {
    n.notify()
}

仔細查看代碼就會發現u是一個結構體類型,而notify方法是使用指針接受者實現的,上述代碼自然就無法編譯通過

數據結構

Golang根據接口類型是否包含一組方法將接口類型分成兩類:

1.使用runtime.iface結構體表示包含方法的接口

type iface struct {
      tab *itab // runtime.itab類型結構體,接口類型的核心組成部分
      data unsafe.Pointer // 指向原始數據的指針
  }

2.使用runtime.eface結構體表示不包含任何方法的interface{}類型

type eface struct {
      _type *_type // 指向類型的指針
      data unsafe.Pointer // 指向底層數據的指針
  }

接口類型不是任意類型

注意:interface{}類型不是任意類型,如果將類型轉換成interface{}類型,變量在運行期間的類型也會發生變化,獲取變量類型時會得到interface{}

package main

type Test struct {}

func NilOrNot(v interface{}) bool {

  return v == nil
}

func main() {

  var s *Test
  fmt.Println(s == nil)
  fmt.Println(NilorNot(s))
}

運行上述代碼時,第一行打印true,第二行會打印false。

出現上述現象的原因就是在調用NilOrNot函數時發生了隱式的類型轉換:*Test類型轉換成interface{},除了這種傳參的情況,在變量賦值也是如此

動態派發(Dynamic dispatch)是在運行期間選擇具體多態操作(方法或函數)執行的過程,接口的引入使得Golang具備了動態派發的特性,即在調用接口類型的方法時,如果編譯期間不能確認接口的類型,則會在運行期間決定具體調用該方法的具體實現

動態派發在結構體上的表現非常差,應當盡量避免使用結構體類型實現接口

以上就是“Go語言接口類型怎么定義”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業資訊頻道。

向AI問一下細節

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

AI

潞西市| 伊春市| 江达县| 西贡区| 理塘县| 民县| 丹东市| 那曲县| 江达县| 浦东新区| 城固县| 绩溪县| 洪江市| 华池县| 怀来县| 玉山县| 湖口县| 茂名市| 崇州市| 申扎县| 加查县| 新丰县| 永州市| 东台市| 武川县| 皮山县| 思茅市| 兖州市| 崇阳县| 锡林郭勒盟| 白银市| 嘉义市| 安化县| 桐庐县| 宜宾市| 缙云县| 武山县| 东台市| 简阳市| 呼和浩特市| 贡嘎县|