使用sync包中断链式方法调用

huangapple go评论75阅读模式
英文:

Break chaining methods using sync package

问题

上次我发现我不需要检查变量是否为nil来创建单例服务,而是可以使用sync.Once来实现相同的结果,下面是一个示例:

// 替代
var instance Instance
func NewInstance() {
    if instance == nil {
        instance = Instance{}
    }
    return instance
}

// 可以这样做
var (
    once sync.Once
    instance Instance
)
func NewInstance() {
    once.Do(func() {
        instance = Instance{}
    })
    return instance
}

我的问题是:
我可以使用sync包来打破链式规则并返回错误吗?

期望的结果:

var (
    breakChain sync.SomethingToBreakChain
    err error
)

type s struct {}

func (s *s) F1() s {
    err = service1.DoSomething()
    // sync 做一些事情
    return s
}
func (s *s) F2() s {
    err = service2.DoSomething()
    // sync 做一些事情
    return s
}
func (s *s) F3() s {
    err = service3.DoSomething()
    // sync 做一些事情
    return s
}
func (s *s) GetError() {
    return err
}

func New() {
    s := s{}
    s.F1(). // 如果发生错误,保存到`err`变量,并在此处中断链式调用,阻止执行`F2`和`F3`
      F2(). // 如果发生错误,保存到`err`变量,并在此处中断链式调用,阻止执行`F3`
      F3() // 如果发生错误,保存到`err`变量并返回
    err := s.GetError()
    // 处理`err`
}
英文:

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

答案1

得分: 3

如果你想实现这样的链式调用,可以考虑在接收器本身保存错误,并在每个操作中进行检查:

type s struct {
  e error
}

func (s *s) F1() *s {
  if s.e != nil {
    return s
  }
  // 做一些事情
  if err := doThings(); err != nil {
     s.e = err
  }
  return s
}
...

否则,没有机制可以阻止在链中调用其他方法。

英文:

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.

huangapple
  • 本文由 发表于 2022年3月3日 04:46:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/71328937.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定