golang學習筆記---在接口和類型之間轉換


1. 類型斷言的格式
接口斷言類似於控制流中的if,但大量類型斷言出現時,應使用更高效的類型分支switch特性。

t := i.(T)

i表示接口變量(斷言對象),T表示要轉換的目標類型(指定類型),t表示轉換后的變量(指定類型接口)。此時,如果i沒有實現T,這個語句會觸發panic。因此,有以下改進寫法:

t, ok := i.(T)

如果斷言對象是指定的類型,則返回指定類型接口;如果不是指定的類型,斷言的第二個參數將返回false。

如果發生接口未實現,go將會把ok置為false,t置為T類型零值;正常實現時,ok為true。這里ok被認為是接口i是否實現類型T的結果。

把接口轉換成其他接口
鳥和豬具有不同特性,鳥可以飛,豬不能飛,但兩種動物都可以走。如果使用結構體實現鳥和豬,讓它們具備各自特性的Fly()和Walk()方法,就能讓鳥和豬各自實現了飛行者接口(Flyer)和行走者接口(Walker)。

對保存有鳥或豬實例的空接口類型interface{}變量進行類型斷言,如果斷言對象是指定的類型,則返回指定類型接口;如果不是指定的類型,斷言的第二個參數將返回false。

package main

import (
    "fmt"
    "testing"
)

// 接口定義
type Flyer interface { // 定義飛行動物接口
    Fly()
}

type Walker interface { // 定義行走動物接口
    Walk()
}

// 接口實現
type bird struct{} // 定義飛行類型

func (b *bird) Fly() { // 實現飛行動物飛行接口
    fmt.Println("bird: fly")
}

func (b *bird) Walk() { // 實現飛行動物行走接口
    fmt.Println("bird: walk")
}

// 接口實現
type pig struct{} // 定義行走類型

func (p *pig) Walk() { // 實現行走動物行走接口
    fmt.Println("pig: walk")
}

func main() {
    // 創建動物名到結構體實例的字典
    animals := map[string]interface{}{
        "bird": new(bird), // 創建出的結構體實例
        "pig":  new(pig),
    }

    // 遍歷字典
    for name, obj := range animals { // obj為字典的值,是interface{}類型
        f, isFlyer := obj.(Flyer)   // 使用類型斷言獲得變量f,轉換后的類型是Flyer;isFlyer是接口類型轉換是否成功的結果
        w, isWalker := obj.(Walker) // 使用類型斷言獲得變量w,轉換后的類型是Walker;isWalker是接口類型轉換是否成功的結果

        fmt.Printf("name: %s isFlyer: %v isWalker: %v\n", name, isFlyer, isWalker)

        if isFlyer {
            f.Fly() // 調用接口方法
        }

        if isWalker {
            w.Walk() // 調用接口方法
        }
    }
}

把接口轉換成其他類型

在go中,接口和其他類型的自由轉換,前提是接口已經實現。

把接口轉換為普通的指針類型。例如,把Walker接口轉換成*pig類型,

package main

import (
    "fmt"
)

// 接口定義
type Flyer interface { // 定義飛行動物接口
    Fly()
}

type Walker interface { // 定義行走動物接口
    Walk()
}

// 接口實現
type bird struct{} // 定義飛行類型

func (b *bird) Fly() { // 實現飛行動物飛行接口
    fmt.Println("bird: fly")
}

func (b *bird) Walk() { // 實現飛行動物行走接口
    fmt.Println("bird: walk")
}

// 接口實現
type pig struct{} // 定義行走類型

func (p *pig) Walk() { // 實現行走動物行走接口
    fmt.Println("pig: walk")
}

func main() {
    p1 := new(pig)

    var a Walker = p1
    p2 := a.(*pig) // 把Walker接口轉換成*pig結構體指針類型

    fmt.Printf("p1=%p p2=%p", p1, p2) // 格式化輸出指針類型
}

// p1=0x118efd0 p2=0x118efd0 ,對比發現p1和p2指針是相同的

在上述代碼中,如果把Walker類型轉換成*bird類型,將會報錯:在接口轉換時,main.Walker接口內部保存的是*main.pig,而不是*main.bird。因此,在接口轉換成其他類型時,接口內保存實例對應的類型指針,必須要轉換成相對應的類型指針。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM