Original post

Hi,

I want to access a struct’s methods (Service.DoThis/DoThat) from within another struct’s methods (Operator.OperateThis/OperateThat). This can be easily done by injecting Service into Operator which is what I am currently doing but I want to avoid it – see the dummy example below please. I simply don’t want to see Service struct in Operator. Is this possible? If so, what is the nicest/cleanest way?

Ideally, I don’t want to inject anything into Operator. However, I can live with injecting anything other than the Service. I looked into variables/types as functions but I couldn’t progress. The critical point here is that, the Service is instantiated once and I want to keep the reference of it.

Thanks

main.go

package main

import "log"

func main() {
        operator := &Operator{}
        StartService(operator)

        if err := operator.OperateThis(); err != nil {
                log.Fatalln(err)
        }

        if err := operator.OperateThat(); err != nil {
                log.Fatalln(err)
        }
}

connection.go

package main

type Connection struct {
        // ...
}
// ...

service.go

package main

type Service struct {
        connection *Connection
        // ...
}

func StartService(operator *Operator) {
        // ...
        operator.SetService(&Service{})
        // ...
}

func (s *Service) DoThis() error {
        s.obtainConnection()
        // ...
        return nil
}

func (s *Service) DoThat() error {
        s.obtainConnection()
        // ...
        return nil
}

// ...

func (s *Service) obtainConnection() {
        s.connection = &Connection{}
}

operator.go

package main

import "log"

type Operator struct {
        service *Service
}

func (o *Operator) SetService(service *Service) {
        o.service = service
}

func (o *Operator) OperateThis() error {
        if err := o.service.DoThis(); err != nil {
                log.Fatalln(err)
        }

        log.Println("operated this")
        return nil
}

func (o *Operator) OperateThat() error {
        if err := o.service.DoThat(); err != nil {
                log.Fatalln(err)
        }

        log.Println("operated that")
        return nil
}

if you change the struct fields with functions, you can use interfaces to hide what you want.

type Operator interface {
    OperateThis() error
    OperateThat() error
}
type Service struct {
        operator Operator
        // ...
}

func StartService(operator Operator) {
        // ...
        operator.SetService(&Service{})
        // ...
}

The other thing is that those structs are very closely coupled. The Service knows about operator and the operator knows about the Service. I think this is the root cause of your issue.