判断BaseApplication 是否实现了Application 全部等接口

type Application interface {
    // Info/Query Connection
    Info(RequestInfo) ResponseInfo                // Return application info
    SetOption(RequestSetOption) ResponseSetOption // Set application option
    Query(RequestQuery) ResponseQuery             // Query for state

    // Mempool Connection
    CheckTx(RequestCheckTx) ResponseCheckTx // Validate a tx for the mempool

    // Consensus Connection
    InitChain(RequestInitChain) ResponseInitChain    // Initialize blockchain w validators/other info from TendermintCore
    BeginBlock(RequestBeginBlock) ResponseBeginBlock // Signals the beginning of a block
    DeliverTx(RequestDeliverTx) ResponseDeliverTx    // Deliver a tx for full processing
    EndBlock(RequestEndBlock) ResponseEndBlock       // Signals the end of a block, returns changes to the validator set
    Commit() ResponseCommit                          // Commit the state and return the application Merkle root hash
}

//-------------------------------------------------------
// BaseApplication is a base form of Application

var _ Application = (*BaseApplication)(nil)

type I interface {
    Sing()
}

type T struct { 
}

func (t T) Sing() {
}

type T2 struct {    
}

func (t *T2) Sing() {
}

// 编译通过
var _ I = T{}
// 编译通过
var _ I = &T{}

// 编译失败
var _ I = T2{}
// 编译通过
var _ I = &T2{}

在这里下划线用来判断结构体是否实现了接口,如果没有实现,在编译的时候就能暴露出问题,如果没有这个判断,后代码中使用结构体没有实现的接口方法,在编译器是不会报错的。

可以看到上面四个判断只有第三个编译时失败的,报错如下:

./test.go:27:5: cannot use T2 literal (type T2) as type I in assignment:
    T2 does not implement I (Sing method has pointer receiver)

这是为什么呢?仔细看上面代码发现,T 实现了 Sing 方法,*T2 实现了 Sing 方法。

我们都知道,Go 语言中是按值传递的。

那对于 T2 来说,调用 Sing 方法时,copy 一个副本,然后取地址,通过这个地址是找不到原始调用的那个结构体的,但是 receiver 是个指针,表示此次调用是需要改变调用者内部变量的,很明显,以 T2 类型调用无法完达到这个目的,所以这里是需要报错的。而以 &T2 调用 Sing 方法,则可以,因此不报错。

而对于 T 来说,不管是否有指针调用,都不会报错,实际上,Go 语言会自动实现 *T 的 Sing 方法。

文章来源于互联网,如有雷同请联系站长删除:Go判断接口是否全部实现

发表评论