Hacker News new | ask | show | jobs
by rakoo 3437 days ago
> With proper composition, your child objects are named, and you can choose which interfaces you want to delegate to which object. This doesn't just give you better control over which functionality you wish to expose, but also avoids conflict when two member objects implement the same interface.

Oh but you can avoid that, it's part of the language, see this link:

https://golang.org/doc/effective_go.html#embedding

Typically, you can have something like this:

    type lockedReader struct {
        io.Reader
        sync.Mutex
    }

    lr := lockerReader{someReader, sync.Mutex{}}
    lr.Lock()
    lr.Read(...)
    lr.Unlock()

By default, methods will be delegated to the first field that has the method. If you want something else, you are free to override this default behavior.
1 comments

No they're not. io.Reader and sync.Mutex do not embed the same type and do not have conflicting methods with the same name.

This is how a diamond looks like:

  type Base struct {
    Foo int32
  }

  type Child1 struct {
    Base
  }

  type Child2 struct {
    Base
  }

  type Diamond struct {
    Child1
    Child2
  }

  func (c *Child1) DoSomething() {
    fmt.Println(c.Foo)
  }

  func (c *Child2) DoSomething() {
    fmt.Println(c.Foo)
  }

  func main() {
    c := Diamond { }
    c.Foo = 42       // Doesn't Compile
    c.Child1.Foo = 10
    c.Child2.Foo = 20
    c.DoSomething()  // Doesn't Compile
  }