我们有2个实现相同功能签名的软件包。在我的主机中,我需要根据以下条件关闭正在使用的软件包:
import (
packageA "deployment/sdk/packageA"
packageB "deployment/sdk/packageB"
)
someCondition := true
var packageToUse ?
if someCondition {
packageToUse = packageA
} else {
packageToUse = packageB
}
packageToUse.DoSomething()
当然,这不会编译。我不知道packageToUse使用什么类型。这种方法可能是一种反模式。我只是不确定我应该采用的方法。
有什么建议吗?
我得到的错误是use of package without selector
答案 0 :(得分:4)
除了动态导入外,这是一种模式。它称为„Interfaces“。
给出类似的接口定义
type Stringer interface{
String() string
}
和实现该接口的Foo类型
type foo int
func(f foo)String() string{
return fmt.Sprintf(”%d”,f)
}
以及实现上述接口的Bar
type bar string
func (b bar) String()string {
return string(b)
}
一个人实际上可以将两者都用作函数baz的参数
func baz(s Stringer){
fmt.Println(s.String())
}
请注意,与其他语言不同,您不必声明类型实现的接口-只要类型碰巧实际上实现了接口,go编译器就可以使用它。 Run on Playground
因此,关于软件包导入的问题:除非您要导入大量依赖树,否则确实不值得麻烦。
说我们谈论使用BBolt或etcd的应用程序,并且很好地衡量了一些MongoDB。虽然相对而言相当惊人,但包含 all 在内的所有结果的大小却可以忽略不计。我用bbolt,bbolt&etcd和bbolt,etcd&mongodb的导入编译了一个go程序。这些是以字节为单位的结果。
11734884 size_all
2455544 size_bolt
10307700 size_boltetcd
我们正在谈论的文件大小为几兆字节。因此,假设您使用Bolt 或 etcd 或 MongoDB,您是否真的想跳过完成动态导入所需的所有步骤?好吗就我而言,我既不想这样做,也不想Go提供这种功能。
“过早的优化是编程中所有(或至少大部分)邪恶的根源。”
–唐纳德·克努斯(Donald Knuth)
答案 1 :(得分:3)
这不是您的要求,但是如果我是您,这就是我要达到的目标:
// I assumed both package functions have the same signature, so you can use a type
// TODO: Actual function signature you want to use here
type myFn func() error
var fnToUse myFn
if someCondition {
fnToUse = packageA.Func1
} else {
fnToUse = packageB.Func2
}
fnToUse()
答案 2 :(得分:0)
在评论有关使用界面的内容之后
我会退后一步,看看是否可以使用 您在条件中为其提供具体类的接口 声明。
package packageA
type Thing struct {
}
func (t Thing) DoSomething() {
}
-
package packageB
type Thing struct {
}
func (t Thing) DoSomething() {
}
-
package main
import (
"packageA"
"packageB"
)
type PackageUser interface {
DoSomething()
}
func main() {
var pu PackageUser
if (condition) {
pu := packageA.Thing{}
} else {
pu := packageB.Thing{}
}
pu.DoSomething()
}