← 返回文章列表

golang學習記錄(11)

Go 基礎學習系列第 11 篇,記錄語法、示例與學習過程。

go語言中interface是一種非常重要的型別,是非常重要的組成部分

1、鴨子型別

鴨子型別

當一隻鳥走起來像鴨子,游泳起來像鴨子,叫起來也想鴨子,那這隻鳥就是鴨子

鴨子型別強調的是事物的方法,而不是內部的結構

也就是說,只要一個物件實現了介面的所有方法,那麼這個物件就可以被認為是實現了這個介面,就能將這個物件作為這個介面的例項

2、介面的定義

介面的定義需要用到type和interface關鍵字,具體的定義格式如下:

type 接口名 interface{
    方法名1(参数列表) 返回值列表
    方法名2(参数列表) 返回值列表
   ...
}

下面是一個例子:

type Duck interface{
    Gaga()
    Walk()
    Swimming()
}

type pskDuck struct{
    legs int
}

func (pd *pskDuck) Gaga(){
    fmt.Println("嘎嘎嘎")
}

func (pd *pskDuck) Walk(){
    fmt.Println("走")
}

func (pd *pskDuck) Swimming(){
    fmt.Println("游泳")
}

func main(){
    var duck Duck = &pskDuck{}
    duck.Gaga()
    duck.Walk()
    duck.Swimming()
}

3、多介面實現

在實際的應用場景中,介面不應該寫的太大,一般一個介面只實現一個方法

type Duck interface{
    Gaga()
}

type Duck2 interface{
    Walk()
}

type Duck3 interface{
    Swimming()
}

type pskDuck struct{}
、
func (pd *pskDuck) Gaga(){
    fmt.Println("嘎嘎嘎")
}

func (pd *pskDuck) Walk(){
    fmt.Println("走")
}

func (pd *pskDuck) Swimming(){
    fmt.Println("游泳")
}

func main(){
    var duck Duck = &pskDuck{}
    var duck2 Duck2 = &pskDuck{}
}

在上面的例子中,pskDuck實現了Duck、Duck2、Duck3三個介面,但是在main函式中,只宣告瞭Duck介面,但是卻可以將pskDuck的例項賦值給Duck介面,這是因為pskDuck實現了Duck介面的所有方法,所以可以將pskDuck的例項賦值給Duck介面

介面也可以作為結構體的引數

介面的使用非常靈活

程式碼的解耦

一個型別實現多個介面。一個介面實現多個型別

……

4、介面與動態型別傳參

斷言

舉個例子,做一個加法計算器:

func add(a, b interface{}) interface{}{
    switch a.(type){
    case int:
        ai, _ := a.(int)
        bi, _ := b.(int)
        return ai + bi

    case int32:
        ai, _ := a.(int32)
        bi, _ := b.(int32)
        return ai + bi
    

    case float32:
        ai, _ := a.(float32)
        bi, _ := b.(float32)
        return ai + bi
    
    //……

    default:
        return 0
    }
}


func main(){
    fmt.Println(add(1, 2))
    fmt.Println(add(1, 3))
    fmt.Println(add(1.0, 2.0))
}

5、介面巢狀

介面巢狀達到程式碼複用的目的

type MyWriter interface{
    Write(string)
}

type MyReader interface{
    Reader() string
}

type MyReaderWriter interface{
    MyReader
    MyWriter
    ReadWriter()
}

type SreadWriter struct{}

func (srw *SreadWriter) Read(){
    fmt.Println("read")
}

func (srw *SreadWriter) Write(){
    fmt.Println("write")
}

func (srw *SreadWriter) ReadWriter(){
    fmt.Println("readWriter")
}

func main(){
    var mrw MyReaderWriter = &SreadWriter{}
    mrw.Read()

}

6、介面與slice常見的錯誤

slice不能作為介面的引數,因為slice是一個引用型別,但是介面是一個值型別,所以不能將slice作為介面的引數,但是可以將slice的指標作為介面的引數

func mPrint(data ... interface{}){
    for _, value := range data{
        fmt.Println(value)
    }
}

func main(){
    //这样是支持的
    var data = []interface{}{
        "aaaaa",
        19,
        1800.00,
    }
    mPrint(data...)
}
關於這篇文章的日期

保留舊站原始文章標註的日期;實際開始寫作的時間可能更早。

原始日期: 2024-10-20 13:59:51 +0800

同一系列 · Go 基礎學習

上一篇golang學習記錄(10) ←下一篇golang學習記錄(12) →