Golang:你能在一个接口中包装一个包吗?

时间:2013-12-27 17:19:52

标签: go duck-typing

我正在编写一个简单的库来协助常见的断言。

type Test interface {
    Fatalf(string, ...interface{})
}

func IsTrue(statement bool, message string, test Test) {
    if !statement {
       test.Fatalf(message)
    }
}

我注意到log包实际上具有Fatalf(string, ...interface{})的兼容实现,如果可以相应地调用IsTrue方法,那就太棒了:

IsTrue(false, "false wasn't true", log)

但我收到错误use of package log not in selector。有没有办法使用或包装一个包来使这个模式工作或者这是不可能的?

2 个答案:

答案 0 :(得分:4)

你可以期待的最好的方法是将它包装在一个空白的结构中,如下所示:

type internalLog struct{}

func (il internalLog) Fatalf(s string, i ...interface{}) {
    log.Fatalf(s, i...)
}

一般来说,由于包不是Go中的类型,因此无法满足任何要求。您必须将它们包装在另一种类型中,以便模拟它们满足界面。

编辑:

正如Caleb提到的(我忘记了),特定中的包log 具有函数New,它返回一个* log.Logger,它将满足{{在你的情况下接口(以及大多数其他包级Test函数)。但是,一般如果没有提供这样的类型,你必须如上所示包装包。

答案 1 :(得分:1)

我会使用log创建一个可以覆盖的默认提供程序:

package main

import (
    "log"
    "os"
)

type TestLogger interface{
    Fatalf(string, ...interface{})
}

var DefaultLogger TestLogger

func init() {
    DefaultLogger = log.New(os.Stderr, "", log.LstdFlags)
}

func IsTrue(statement bool, message string) {
    if !statement {
       DefaultLogger.Fatalf(message)
    }
}

func main() {
    IsTrue(false, "MESSAGE")
}

如果有人在使用您的包裹,他们可以这样做:

type MyCustomImplementation struct {}

func (this MyCustomImplementation) Fatalf(msg string, args ... interface{}) {
    // do whatever in here
}

some_package.DefaultLogger = MyCustomImplementation{}