How to dependency inject database clients into structs in golang?

Viewed 69

I am trying to use dependency injection to inject a database client in the struct using go language. Unfortunately, I did not understand how this could be done as i only see basic examples in the internet from which i am unable to get complete picture.

I have a Producer interface which is having different implementations. I also have a client for redis/kafka to produce messages.

package producers

type IProducer interface {
    setMessageType(messageType string)
    setTopic(topic string)
    getMessageType() string
    getTopic() string
}

type Producer struct {
    messageType string
    topic       string
}
// producer implements the IProducer

type UserLocationProducer struct {
    Producer
}

func newUserLocationProducer() IProducer {
    return &UserLocationProducer{
        Producer: Producer{
            messageType: "user_location",
            topic:       "user_location",
        },
    }
}

Redis client code

type RedisClient struct {
    pool *redis.Pool
}

func NewRedisClient(addr string, dn int, passwd string) *RedisClient {
    // code to create client
    return client
}

Now my question is if i want to inject RedisClient into Producer how can i achieve it. I am basically from Java background where i will wire my dependencies using Spring and Autowiring the dependency. Any pointers is very much appreciated.

1 Answers

Dependency injection can be done here by using interfaces, which act as a commonality between the different clients, e.g. below is one of the ways this can be done.

A Client interface that both kafka/redis clients satisfy

type Client interface{
    Publish(<message etc fields>)
}

func (redisClient RedisClient) Publish(<message etc fields>){
    //Do client things
}

IProducer: new method to set client (kafka/redis).

type IProducer interface {
    ...
    SetClient(client Client)
}

Producer: field for reference to the client, and setter method,

type Producer struct {
    ...
    client Client
}

func (producer Producer)SetClient(clt Client){
    producer.client = clt
}

func (producer Producer)send(){
    client.Publish(<message etc fields>)
}

Client interface can be mocked for testing and injected same way into Producer

Also Instead of SetClient method field client can be set directly while creating Producer, Just that setter methods give a bit more control.

Related