如何引用具有相同功能的多个库并在Go中内联切换它们
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何引用具有相同功能的多个库并在Go中内联切换它们相关的知识,希望对你有一定的参考价值。
我想知道我怎么能做类似的事情。我目前有多个包具有相同的结构和功能,但它们实际上从多个API检索值。我也在一个配置中加载一个带有参数的数组,以便每个数组项使用其中一个包。我想知道如何根据配置值创建一个使用其中一个包的变量。希望这很清楚。这是我编写的伪代码解释。提前致谢
package main
import (
"errors"
"flag"
"os"
"project/lib"
"project/morelib"
"project/extralib"
"fmt"
"math"
"math/rand"
"time"
)
func stuff(info RunInfo) (err error) {
apiKey:= "stuff1" // actually in the config
apiSecret := "stuff2" // actually in the config
variable := lib.New(apiKey, apiSecret) //returns *Lib struct
//this is where I have to comment out the other libs and uncomment them as needed
// variable := morelib.New(apiKey, apiSecret)
// variable := extralib.New(apiKey, apiSecret)
//trying to switch between libraries like this or in a switch statement
if info.libname == "lib"{
variable = lib.New(apiKey, apiSecret) //.New("", "") returns *Lib struct
}else if info.libname == "morelib"{
variable = morelib.New(apiKey, apiSecret) //.New("", "") returns *MoreLib struct
}else if info.libname == "extralib"{
variable = extralib.New(apiKey, apiSecret) //.New("", "") returns *ExtraLib struct
}else{
err = errors.New("there was an error with the value.....")
return err
}
mystuffs, err := variable.GetBalance("USD")
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("mystuff value: %v", mystuffs.value)
return
}
type RunInfo struct{
libname string
//other stuff
}
func main() {
//load from config with array
config := config.Load()
for i:=0; i<compare; i++{
var runInfo RunInfo
runInfo.libname = config.libname
stuff(runInfo)
}
}
伪lib代码:
func New(apiKey, apiSecret string) *Lib {
client := NewClient(apiKey, apiSecret)
return &Lib{client}
}
func NewClient(apiKey, apiSecret string) (c *client) {
return &client{apiKey, apiSecret, &http.Client{}, false}
}
type Lib struct {
client *client
}
type client struct {
apiKey string
apiSecret string
httpClient *http.Client
debug bool
}
func (b *Lib) GetBalance(currency string) (balance Balance, err error) {
payload, err := json.Marshal(BalanceParams{Currency: currency})
if err != nil {
return
}
r, err := b.client.do("POST", "GetBalance", string(payload), true)
if err != nil {
return
}
var response jsonResponse
if err = json.Unmarshal(r, &response); err != nil {
return
}
if err = handleErr(response); err != nil {
return
}
err = json.Unmarshal(response.Result, &balance)
return
}
答案
使用if和if语句作为问题,switch语句或映射。
我假设New
函数返回的类型是以下接口:
type GetStuffer interface
GetStuff(string) (Stuff, error)
}
switch语句是:
var variable GetStuffer
switch info.CompareVal {
case "lib":
variable = lib.New(string1, string2)
case "morelib":
variable = morelib.New(string1, string2)
case "extralib":
variable = extralib.New(string1, string2)
default:
return errors.New("there was an error with the value.....")
}
mystuffs, err := variable.GetMyStuff()
if err != nil {
fmt.Println(err)
return
}
对于地图,使用地图初始化包级别变量:
var m = map[string]func(string,string) GetStuffer {
"lib": lib.New,
"morelib": morelib.New,
"extralib": extralib.New,
}
并像这样使用它:
fn := m[info.CompareValue]
if m == nil {
return errors.New("there was an error with the value.....")
}
variable := fn(string1, string2)
mystuffs, err := variable.GetMyStuff()
if err != nil {
fmt.Println(err)
return
}
如果上面关于返回类型的假设不正确,那么有两个选项。第一个也可能是最简单的是修改New
函数以返回类型GetStuffer
。如果那是不可能的,那么写一些小适配器功能:
var m = map[string]func(string,string) GetStuffer {
"lib":func(s1, s2 string) GetStuffer { return lib.New(s1, s2) }
"morelib":func(s1, s2 string) GetStuffer { return morelib.New(s1, s2) }
"extralib":func(s1, s2 string) GetStuffer { return extralib.New(s1, s2) }
}
另一答案
为什么不定义一个只有一个功能的接口?在你的例子中
type Stuffer interface {
GetMyStuff(string) (Stuff, error)
}
然后将变量声明为类型Stuffer
。
以上是关于如何引用具有相同功能的多个库并在Go中内联切换它们的主要内容,如果未能解决你的问题,请参考以下文章
如何在云功能中的两个 Firebase 项目之间切换? [复制]