溫馨提示×

溫馨提示×

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

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

golang中結構體嵌套接口如何實現(xiàn)

發(fā)布時間:2023-04-03 10:24:16 來源:億速云 閱讀:80 作者:iii 欄目:開發(fā)技術

今天小編給大家分享一下golang中結構體嵌套接口如何實現(xiàn)的相關知識點,內(nèi)容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。

在golang中結構體A嵌套另一個結構體B見的很多,可以擴展A的能力。

A不僅擁有了B的屬性,還擁有了B的方法,這里面還有一個字段提升的概念。

示例:

package main

import "fmt"

type Worker struct {
    Name string
    Age int
    Salary
}

func (w Worker) fun1() {
    fmt.Println("Worker fun1")
}

type Salary struct {
    Money int
}

func (s Salary) fun1() {
    fmt.Println("Salary fun1")
}
func (s Salary) fun2() {
    fmt.Println("Salary fun2")
}

func main() {
    s := Salary{}
    w := Worker{Salary: s}

    //w.Name
    //w.Age
    //w.Money
    //w.Salary
    //w.fun1()
    //w.fun2()
    //w.Salary.fun1()
    //w.Salary.fun2()
}

很明顯現(xiàn)在 Worker 強依賴與 Salary ,有時候我們希望 Worker 只依賴于一個接口,這樣只要實現(xiàn)了此接口的對象都可以傳遞進來。

優(yōu)化后:

package main

import "fmt"

type Inter1 interface {
    fun1()
    fun2()
}

type Worker struct {
    Name string
    Age int
    Inter1
}

func (w Worker) fun1() {
    fmt.Println("Worker fun1")
}

type Salary struct {
    Money int
}

func (s Salary) fun1() {
    fmt.Println("Salary fun1")
}
func (s Salary) fun2() {
    fmt.Println("Salary fun2")
}

func main() {
    s := Salary{}
    w := Worker{Inter1: s}

    //w.Age
    //w.Name
    //w.fun1()
    //w.fun2()
    //w.Inter1
    //w.Inter1.fun1()
    //w.Inter1.fun2()
    // 無法訪問 Money 屬性,可以增加方法來實現(xiàn)
}

Worker 依賴一個 Inter1 接口,只要實現(xiàn)了 Inter1 的對象都可以注入。
Worker 也實現(xiàn)了 Inter1 接口。
Worker 可以重新實現(xiàn) Inter1 接口的方法。

golang的context標準庫就是這樣實現(xiàn)的context之間的嵌套。

另外,需要注意的是,一個結構體包含了一個接口,那么此結構體自然就是這個接口的一個實現(xiàn),即便這個結構體沒有實現(xiàn)任何方法

type man interface {
    Eat(args ...any)
}

type dog struct {
    man
}

func testDog() {
    d := dog{}
    d.Eat(1)
}

顯然這里的調(diào)用會報錯。

golang接口的這種隱式的實現(xiàn)特性,會導致某個對象無意間就實現(xiàn)了某個接口,然而對于一些底層接口卻需要保持其封閉性,為了達到這個目的,通常的做法是,在接口中有特殊含義的方法,比如runtime.Error接口,注釋就說明了意圖

// The Error interface identifies a run time error.
type Error interface {
    error

    // RuntimeError is a no-op function but
    // serves to distinguish types that are run time
    // errors from ordinary errors: a type is a
    // run time error if it has a RuntimeError method.
    RuntimeError()
}

或者定義一個無法導出的方法,這樣在包外面就無法被實現(xiàn)了,比如testing.TB接口

// TB is the interface common to T, B, and F.
type TB interface {
    Cleanup(func())
    Error(args ...any)
    Errorf(format string, args ...any)
    Fail()
    FailNow()
    Failed() bool
    Fatal(args ...any)
    Fatalf(format string, args ...any)
    Helper()
    Log(args ...any)
    Logf(format string, args ...any)
    Name() string
    Setenv(key, value string)
    Skip(args ...any)
    SkipNow()
    Skipf(format string, args ...any)
    Skipped() bool
    TempDir() string

    // A private method to prevent users implementing the
    // interface and so future additions to it will not
    // violate Go 1 compatibility.
    private()
}

第一種方法顯然只能防君子,不能防小人。

第二種方法看起來比較安全,但是結合我們上面的知識,如果使用結構體來包含這個接口呢?是不是也能實現(xiàn)這個接口?

type MyTB struct {
    testing.TB
}

顯然MyTB已經(jīng)實現(xiàn)了testing.TB,但是此時調(diào)用是會報錯的

func main() {
    tb := new(MyTB)
    tb.Fatal("hello", "world")
}

實現(xiàn)其中的一個方法,再調(diào)用即可

func (p *MyTB) Fatal(args ...interface{}) {
    fmt.Println(args...)
}

func main() {
    tb := new(MyTB)
    tb.Fatal("hello", "world")
}

既然MyTB實現(xiàn)了testing.TB,那么就可以做隱式轉換

var tb testing.TB = new(MyTB)
tb.Fatal("hello", "world")

以上就是“golang中結構體嵌套接口如何實現(xiàn)”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業(yè)資訊頻道。

向AI問一下細節(jié)

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

AI