英文:
Golang: Can you wrap a Package in an Interface?
问题
我正在编写一个简单的库来辅助常见的断言。
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
。有没有办法使用或包装一个包来使这种模式工作,或者这不可能实现?
英文:
I'm writing a simple library to assist with common assertions.
type Test interface {
Fatalf(string, ...interface{})
}
func IsTrue(statement bool, message string, test Test) {
if !statement {
test.Fatalf(message)
}
}
I noticed that the log
package actually has a compatible implementation of Fatalf(string, ...interface{})
and it'd be great if the IsTrue
method could be invoked accordingly:
IsTrue(false, "false wasn't true", log)
But I get the error use of package log not in selector
. Is there any way to use or wrap a package to make this pattern work or is this not possible?
答案1
得分: 5
你最好的选择是将其包装在一个空白结构体中,像这样:
type internalLog struct{}
func (il internalLog) Fatalf(s string, i ...interface{}) {
log.Fatalf(s, i...)
}
一般来说,在Go语言中,由于包不是类型,它们不能满足任何接口。你必须将它们包装在另一个类型中,以模拟它们满足接口的情况。
编辑:
正如Caleb提到的(我忘了),特定的log
包具有New
函数,它返回一个*log.Logger类型,该类型将满足你的情况下的Test
接口(以及大多数其他包级别的log
函数)。然而,一般情况下,如果没有提供这样的类型,你必须像我上面展示的那样包装该包。
英文:
The best you can hope for is to wrap it in a blank struct like so:
type internalLog struct{}
func (il internalLog) Fatalf(s string, i ...interface{}) {
log.Fatalf(s, i...)
}
In general, since packages are not types in Go, they cannot satisfy anything. You have to wrap them in another type in order to simulate them satisfying an interface.
Edit:
As Caleb mentions (and I forgot about), the package log
in specific has the function New
which returns a *log.Logger which will satisfy the Test
interface in your case (as well as most other package-level log
functions). However, in general if no such type is provided you must wrap the package like I showed above.
答案2
得分: 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{}) {
// 在这里进行自定义操作
}
some_package.DefaultLogger = MyCustomImplementation{}
英文:
I would make a default provider using log
that can be overwritten:
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")
}
If someone was using your package they could do something like this:
type MyCustomImplementation struct {}
func (this MyCustomImplementation) Fatalf(msg string, args ... interface{}) {
// do whatever in here
}
some_package.DefaultLogger = MyCustomImplementation{}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论