go 空接口

golang 的接口類型是對具體類型/結構體的行為進行泛化或抽象,接口的特點是靈活。
接口類型指定了一系列的方法,具體類型必須實現(xiàn)所有的方法才能視為該接口的實例。

package main

import (
    "fmt"
    "strings"
)

// var talker interface {
//  talk() string
// }

type talker interface {
    talk() string
}

type martain struct{}

func (m martain) talk() string {
    return "nack nack"
}

type laser int

func (l laser) talk() string {
    return strings.Repeat("pew ", int(l))
}

func shout(t talker) {
    louder := strings.ToUpper(t.talk())
    fmt.Printf("%v\n", louder)
}

func main() {
    tmp := martain{}
    shout(tmp)  // NACK NACK
    shout(laser(3))  // PEW PEW PEW
}

上述代碼聲明了talker接口,該接口有一個talk()方法,有兩個具體類型martain、laser都各自實現(xiàn)了該方法。一個shout()函數(shù)的入?yún)⑹莟alker接口類型的,這兩種具體類型的變量都可以調(diào)用shout(),因為都實現(xiàn)了talker接口。

關于golang的接口類型,書本或者網(wǎng)上都介紹很詳細,今天主要來研究一下空接口。

空接口

函數(shù)入?yún)?/h2>

golang可以使用空接口作為函數(shù)的入?yún)?,表示可接受任意類型的變量?/p>

package main

import "fmt"

type point struct {
    x int
    y int
}

func show(any interface{}) {
    fmt.Println(any)
}

func main() {
    show(12)
    show("abc")
    show(true)
    show(point{1, 2})
}

有興趣的小伙伴可以看看go的源碼中對于fmt.Println()函數(shù)的定義,就是空接口作為入?yún)?,因此Println()可以打印任意類型的數(shù)據(jù)。

類型斷言

空接口可以存儲任意類型的變量,當我們需要獲取變量的具體類型時,可通過斷言來動態(tài)地get。

package main

import "fmt"

func main() {
    // 注意,把空接口作為任意類型的變量時,
    //它本身也是一個變量,需要使用var關鍵字;而不是聲明接口類型的type關鍵字
    var any interface{}
    any = 12
    value, ok := any.(int)
    if !ok {
        fmt.Println("it's not int type")
        return
    }
    fmt.Printf("%v\n", value)  // 輸出:12
}

如果把any賦值為string或者除int的其他任意類型,再執(zhí)行代碼時就會執(zhí)行到if 語句中,然后退出程序。因為any不是int類型的變量,斷言為false,得到的不是我們想要的類型,當然應該中止程序。


圖片.png

斷言還可以是切片、map:

func main() {
    var any interface{} = []string{"a", "b", "c"}
    value, ok := any.([]string)
    if !ok {
        fmt.Println("it's not string slice type")
        return
    }
    for i, v := range value {
        fmt.Printf("%d  %s\n", i, v)
    }

    any = map[string]int{"zhangsan": 1, "lisi": 2}
    value1, ok := any.(map[string]int)
    if !ok {
        fmt.Println("it's not map[string]int type")
        return
    }
    for k, v := range value1 {
        fmt.Printf("%v  %v\n", k, v)
    }
}

結構體其實和map類似,就不列舉了。

[]interface{}

在go語言中還有這樣的類型[]interface{}
通過前面的學習,聰明的你再舉一反三,立馬就明白了這個接口切片是任意類型的切片的意思。
可惜答案卻大錯特錯。

func show(any []interface{}) {
    for i, v := range any {
        fmt.Printf("%d %v\n", i, v)
    }
}

func main() {
    strArr := []string{"a", "b", "c"}
    show(strArr)
}

上面這段代碼甚至在代碼編寫時就報錯了,無法通過編譯,原因是cannot use strArr (variable of type []string) as []interface{} value in argument to show。
以后的使用場景中肯定會遇到很多[]interface{}的場景(尤其是在解析json數(shù)據(jù)時),請務必記住,[]interface{}!=[]anyType{}。
畢竟interface{}已經(jīng)代表了任意類型,包含了任意類型的切片,為什么還要再重復定義一個[]interface{}來表示任意類型的切片呢?
[]interface{}是一個具體的類型。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • 大家好,我是謝偉,是一名程序員。 下面的學習是一個系列,力求從初學者的角度學會go 語言,達到中級程序員水平。 這...
    謝小路閱讀 2,018評論 0 6
  • 接口(interface)是一種抽象的類型,是對其他類型行為的概括和抽象。從語法角度來看,接口是一組方法簽名定義的...
    JunChow520閱讀 493評論 0 1
  • 原文:https://makeoptim.com/golang/effective-go[https://make...
    CatchZeng閱讀 2,058評論 0 1
  • reflection 反射(reflection)是程序在運行時通過檢查其定義的變量和值獲得對應的真實類型。 在計...
    JunChow520閱讀 1,962評論 0 5
  • 這篇文章就總結一下go 的細節(jié)具體參考:http://c.biancheng.net/golang/[http:/...
    天空藍雨閱讀 698評論 0 0

友情鏈接更多精彩內(nèi)容