簡體   English   中英

確保類型在 Go 編譯時實現接口

[英]Ensure a type implements an interface at compile time in Go

如何確保類型在編譯時實現接口? 執行此操作的典型方法是無法分配該類型的支持接口,但是我有幾種僅動態轉換的類型。 在運行時,這會生成非常粗魯的錯誤消息,而沒有為編譯時錯誤提供更好的診斷。 在運行時找到我希望支持接口的類型也很不方便,實際上不支持。

假設問題是關於圍棋,例如

var _ foo.RequiredInterface = myType{} // or &myType{} or [&]myType if scalar

因為 TLD 會在編譯時為您檢查。

在 Go 語言中,設計上沒有“實現”聲明。 要求編譯器通過嘗試賦值來檢查類型T實現了接口I的唯一方法(是的,一個虛擬的)。 注意,Go lang 區分在結構體和指針上聲明的方法,在賦值檢查中使用正確的方法

type T struct{}
var _ I = T{}       // Verify that T implements I.
var _ I = (*T)(nil) // Verify that *T implements I.

閱讀 FAQ 了解詳情為什么 Go 沒有“實現”聲明?

通過@smile-on 擴展答案。

我如何保證我的類型滿足接口? ,這是 Go 作者的常見問題 (FAQ)的一部分,聲明如下:

您可以通過嘗試使用T的零值或指向T指針(視情況而定)來要求編譯器檢查類型T實現了接口I

我們可以用一個例子來說明這一點:

package main

type I interface{ M() }
type T struct{}

func (T) M() {}

//func (*T) M() {} //var _ I = T{}: T does not implement I (M method has pointer receiver)

func main() {
  //avoids allocation of memory
  var _ I = T{}       // Verify that T implements I.
  var _ I = (*T)(nil) // Verify that *T implements I.
  //allocation of memory
  var _ I = &T{}      // Verify that &T implements I.
  var _ I = new(T)    // Verify that new(T) implements I.
}

如果T (或*T ,相應地)沒有實現I ,錯誤將在編譯時被捕獲。 請參閱接口實現中的非接口方法

通常,如果您不知道某個值的類型,則檢查該值是否實現了接口。 如果已知,則檢查由編譯器自動完成。 請參閱檢查值是否實現接口的說明

空白標識符_代表變量名,這里不需要它(從而防止“聲明但未使用”錯誤)。 (*T)(nil)通過將nil轉換為*T來創建一個指向T類型值的未初始​​化指針。 請參閱理解一段 golang 代碼時遇到問題

這與例如var t *T在分配任何內容之前具有的值相同。 請參閱golang 接口合規性編譯類型檢查 這避免了像使用&T{}new(T)那樣為空結構分配內存。 請參閱理解一段 golang 代碼時遇到問題

行情編輯以匹配示例。

像這樣:

http://play.golang.org/p/57Vq0z1hq0

package main

import(
    "fmt"
)

type Test int

func(t *Test) SayHello() {
    fmt.Println("Hello");   
}

type Saluter interface{
    SayHello()
    SayBye()
}

func main() {
    t := Saluter(new(Test))
    t.SayHello()
}

將產生:

prog.go:19: cannot convert new(Test) (type *Test) to type Saluter:
    *Test does not implement Saluter (missing SayBye method)
package main

import (
    "fmt"
)

type Sayer interface {
    Say()
}

type Person struct {
    Name string
}

func(this *Person) Say() {
    fmt.Println("I am", this.Name)
}

func main() {
    person := &Person{"polaris"}

    Test(person)
}

func Test(i interface{}) {
    //!!here ,judge i implement Sayer
    if sayer, ok := i.(Sayer); ok {
        sayer.Say()
    }
}

代碼示例在這里: http : //play.golang.org/p/22bgbYVV6q

我不喜歡通過在主代碼中放置虛擬行來使編譯器拋出錯誤的想法。 這是一個有效的智能解決方案,但我更喜歡為此目的編寫測試。

假設我們有:

type Intfc interface { Func() }
type Typ int
func (t Typ) Func() {}

此測試確保Typ實現Intfc

package main

import (
    "reflect"
    "testing"
)

func TestTypes(t *testing.T) {
    var interfaces struct {
        intfc Intfc
    }
    var typ Typ
    v := reflect.ValueOf(interfaces)
    testType(t, reflect.TypeOf(typ), v.Field(0).Type())
}

// testType checks if type t1 implements interface t2
func testType(t *testing.T, t1, t2 reflect.Type) {
    if !t1.Implements(t2) {
        t.Errorf("%v does not implement %v", t1, t2)
    }
}

您可以通過將它們添加到TestTypes函數來檢查所有類型和接口。 這里介紹為 Go 編寫測試。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM