How to make a struct field a generic type

Issue

I am importing two (and more to come) external libraries which are related in function, but distinct from each other. I’d like to be able to do the following:

  • create a new object of each
  • assign each to a field of a nested struct
  • be able to access the library methods by using the nested struct’s field

Roughly something like this:

import (
    "github.com/bittrex_api_wrapper"
    "github.com/kraken_api_wrapper"
)

type Exchange struct {
    bittrex     *data
    kraken      *data
}

type data struct {
    cntr      int
    api       ????    
}

func Initialize() Exchange {
    e Exchange

    brex := bittrex_api_wrapper.New("APIKEY1", "SECRET1")
    krak := kraken_api_wrapper.New("APIKEY2", "SECRET2")

    brexData := data {
        cntr:    0,
        api:     brex,
    }
    krakData := data {
        cntr:    0,
        api:     krak,
    }
    e = Exchange {
        bittrex:    brexData,
        kraken:     krakData,
    }

    return e
}

func (e *Exchange) CheckBalance(exng string) float64 {
    switch exng {
        case "kraken":
            return e.kraken.api.Balance()
        case "bittrex":
            return e.bittrex.api.Balance()
    }
}

In my search for an answer, it seems like the reflect package or an interface might be my solution (or some combination of the two), but I’m not a developer and very new to Go, so Reflect was a little over my head.

Any help is much appreciated!

Solution

Use interface:

type balancer interface {
  Balance() int64
}

type data struct {
    cntr      int
    api       balancer
}

Note that unlike many other OO languages which claim they have interfaces,
in Go, this concept “is backwards”: you can define any interface and then
make the Go runtime make sure the value you’re assigning to a variable of that custom interface 1) satisfies that interface, and 2) allows directly calling the interface methods on it.
That is, any data structure coming from any external code can
potentially support any number of interfaces without being aware of this.

You may start with this.

Note that the indicated approach only works if both “wrapper” packages
you import define their respective data types in such a way that they have
identical Balance() function, and this means they must have the same return type (or have none, both).

Answered By – kostix

Answer Checked By – Katrina (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.