根据条件选择包装

时间:2019-06-28 18:51:23

标签: go

我们有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

3 个答案:

答案 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()
}