DEV Community

Roman Romadin
Roman Romadin

Posted on

10 3 1

Go (golang) service options (dependencies)

How to dynamically inject dependencies into "Service" in Go?

This solution (approach) is based on:

  1. variadic functions (https://yourbasic.org/golang/variadic-function/) and
  2. self-referential functions (https://www.geeksforgeeks.org/self-referential-structures/).

At first glance, this seems a bit confusing, but it's actually a simple solution.
This approach can be used to initialize the application as a whole and to load configuration and other services.

Using variadic function:

type Option func(*accs)

func (f *accs) AddOptions(opts ...Option) {
    for _, opt := range opts {
        opt(f)
    }
}
Enter fullscreen mode Exit fullscreen mode

Using self-referential functions:

func BindSubscriptions(v subscriptions.Client) Option {
    return func(f *accs) {
        f.srvSubscriptions = v
    }
}
Enter fullscreen mode Exit fullscreen mode

First of all you should create main service. In our snippet it is accounts:

accs := accounts.New()
Enter fullscreen mode Exit fullscreen mode

Init the second service (it will be property for main service):

srvSubscriptions := subscriptions.New(111)
Enter fullscreen mode Exit fullscreen mode

After that you should bind second service and set properties for first service:

sbs := accounts.BindSubscriptions(srvSubscriptions)
accs.AddOptions(sbs)
Enter fullscreen mode Exit fullscreen mode

And finally we process business logic (process):

accs.Process(222)
Enter fullscreen mode Exit fullscreen mode

As well we can change any properties in second service (accounts or billing in our snippet): set value = 222

And in addition by using variadic functions we can add one or more properties into first service:

accs.AddOptions(sbs, bl)
Enter fullscreen mode Exit fullscreen mode

or by this way:

accs.AddOptions(sbs)
accs.AddOptions(bl)
Enter fullscreen mode Exit fullscreen mode

Full code:

.
├── cmd
│   └── main.go
├── pkg
│   ├── accounts
│   │   └── service.go
│   ├── billing
│   │   └── service.go
│   └── subscriptions
│       └── service.go
└── README.md
Enter fullscreen mode Exit fullscreen mode
package main

import (
    "../pkg/billing"
    "../pkg/subscriptions"
    "../pkg/accounts"
    "fmt"
)

func main() {
    fmt.Println("Variant_1:")
    variant1()

    fmt.Println("Variant_2:")
    variant2()

    fmt.Println("Variant_3:")
    variant3()
}


func variant1() {
    accs := accounts.New()

    srvAccounts := subscriptions.New(111)

    sbs := accounts.BindSubscriptions(srvAccounts)

    accs.AddOptions(sbs)

    accs.Process(222)
}

func variant2() {
    accs := accounts.New()

    srvAccounts := subscriptions.New(333)
    srvBilling := billing.New()

    sbs := accounts.BindSubscriptions(srvAccounts)
    bl := accounts.BindBilling(srvBilling)

    accs.AddOptions(sbs, bl)

    accs.Process(444)
}

func variant3() {
    accs := accounts.New()

    srvAccounts := subscriptions.New(555)
    srvBilling := billing.New()

    sbs := accounts.BindSubscriptions(srvAccounts)
    bl := accounts.BindBilling(srvBilling)

    accs.AddOptions(sbs)
    accs.AddOptions(bl)

    accs.Process(777)
}


Enter fullscreen mode Exit fullscreen mode

Output result:

Variant_1:
        a.Prop (before): 111
        a.Prop (after): 222

Variant_2:
        a.Prop (before): 333
        a.Prop (after): 444

Variant_3:
        a.Prop (before): 555
        a.Prop (after): 777

Enter fullscreen mode Exit fullscreen mode
Thank you for reading.

All sources you can find in my repository:
https://github.com/romanitalian/go-service-options

PR's are welcome.

Heroku

Build apps, not infrastructure.

Dealing with servers, hardware, and infrastructure can take up your valuable time. Discover the benefits of Heroku, the PaaS of choice for developers since 2007.

Visit Site

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay