如何在Go中内联引用具有相同功能的多个库并在它们之间进行内联切换

I am wondering how I can do something similar to this. I currently have multiple packages with that same structure and functions but they actually retrieve values from multiple APIs. I am also loading in a config that has an array with parameters to use one of those packages per array item. I am wondering how I can create a variable that uses one of those packages based on the config value. Hopefully this is clear enough. Here is pseudo code that I have written up to explain. Thanks in advance

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)
    }
}

pseudo lib code:

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
}

Use and if statement as in the question, a switch statement or a map.

I assume that the type returned by the New function is the following interface:

type GetStuffer interface 
    GetStuff(string) (Stuff, error)
}

The switch statement is:

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
}

For the map, initialize a package level variable with the map:

var m = map[string]func(string,string) GetStuffer {
   "lib": lib.New,
   "morelib": morelib.New,
   "extralib": extralib.New,
}

and use it like this:

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
}

If the assumption above about the return type is not correct, then there are two options. The first and likely the simplest is to modify New functions to return type GetStuffer. If that's not possible, then write little adaptor functions:

 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) }
}

Why don't you define an interface that's only one function? In your example would be

type Stuffer interface {
   GetMyStuff(string) (Stuff, error)
}

Then you declare your variable as type Stuffer.