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

4

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

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)

但我遇到了错误使用了不在选择器中的log包。有没有办法使用或包装一个包来使这个模式工作,或者这不可能?


这是关于Go FAQ中你正在进行的事情的一条智慧金句: http://golang.org/doc/faq#testing_framework 。 - Paul Hankin
2个回答

5
你最好的选择是将其包装在一个空结构体中,就像这样:
type internalLog struct{}

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

通常来说,在Go中,由于包不是类型,它们无法满足任何要求。你必须将它们包装在另一个类型中,以模拟它们满足接口的情况。
编辑:
正如Caleb所提到的(我忘了),特定的包log有函数New,它返回一个* log.Logger类型,这将满足您的情况下的Test接口(以及大多数其他包级别的log函数)。然而,在一般情况下,如果没有提供这样的类型,则必须像上面所示的那样包装该包。

自2013年以来,有没有任何更改/改进/增强的功能? - neleus

2
我会创建一个默认的提供程序,使用“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{}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接