Break chaining methods using sync package

Issue

Last time I found out I didn’t have to check if variable is nil to make singleton service but I can use sync.Once to achieve the same result, example below:

// instead of
var instance Instance
func NewInstance() {
    if instance == nil {
        instance = Instance{}
    }
    return instance
}

// can do this
var (
    once sync.Once
    instance Instance
)
func NewInstance() {
    once.Do(func() {
        instance = Instance{}
    })
    return instance
}

My question is:
Can I use sync package to break chaining rules and return error?

Desired result:

var (
    breakChain sync.SomethingToBreakChain
    err error
)

type s struct {}

func (s *s) F1() s {
    err = service1.DoSomething()
    // sync do something
    return s
}
func (s *s) F2() s {
    err = service2.DoSomething()
    // sync do something
    return s
}
func (s *s) F3() s {
    err = service3.DoSomething()
    // sync do something
    return s
}
func (s *s) GetError() {
    return err
}

func New() {
    s := s{}
    s.F1(). // if error save to `err` variable and break chain here prevent `F2` and `F3` to execute
      F2(). // if error save to `err` variable and break chain here prevent `F3`  to execute
      F3() // if error save to `err` to return
    err := s.GetError()
    // do something with `err`
}

Solution

If you want to implement a chain like that, you might consider saving the error in the receiver itself and checking in every action:

type s struct {
  e error
}

func (s *s) F1() *s {
  if s.e!=nil {
    return s
  }
  // Do things
  if err:=doThings(); err!=nil {
     s.e=err
  }
  return s
}
...

Otherwise, there are no mechanisms to prevent calling other methods in the chain.

Answered By – Burak Serdar

Answer Checked By – Cary Denson (GoLangFix Admin)

Leave a Reply

Your email address will not be published.