Go (golang) service options (dependencies)
Tags: go, options, dependencies
Published: 2020-02-15 10:28:07

---
title: Go (golang) service options (dependencies)
published: true
description: How to add optional service property (option/dependency) into main service
tags: go, golang, 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`:

```go
type Option func(*accs)

func (f *accs) AddOptions(opts ...Option) {
    for _, opt := range opts {
        opt(f)
    }
}
```

Using `self-referential functions`:
```go
func BindSubscriptions(v subscriptions.Client) Option {
    return func(f *accs) {
        f.srvSubscriptions = v
    }
}
```


First of all you should create main service. In our snippet it is `accounts`:
```go
accs := accounts.New()
```

Init the second service (it will be property for main service):
```go
srvSubscriptions := subscriptions.New(111)
```

After that you should bind second service and set properties for first service:
```go
sbs := accounts.BindSubscriptions(srvSubscriptions)
accs.AddOptions(sbs)
```


And finally we process business logic (process):
```go
accs.Process(222)
```
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:
```go
accs.AddOptions(sbs, bl)
```
or by this way:
```go
accs.AddOptions(sbs)
accs.AddOptions(bl)
```

Full code:
```
.
├── cmd
│   └── main.go
├── pkg
│   ├── accounts
│   │   └── service.go
│   ├── billing
│   │   └── service.go
│   └── subscriptions
│       └── service.go
└── README.md
```

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


```



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

```


<center>Thank you for reading.</center>

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



PR's are welcome.