Skip to content

Embedding Interfaces — Find the Bug

Bug 1 — Method conflict

type A interface { M() string }
type B interface { M() int }
type AB interface { A; B }
Bug: Compile error — different signatures. Fix: Make the signatures match or rename the methods.


Bug 2 — Cyclic embed

type A interface { A }
Bug: Compile error — circular. Fix: Make the hierarchy explicit.


Bug 3 — Pointer to interface embed

type ReadWriter interface { *Reader; Writer }
Bug: Compile error — you can't embed a pointer to an interface. Fix: Reader (pointer-siz).


Bug 4 — Nested embed conflict

type A interface { Foo() string }
type B interface { Foo() int }
type AB interface { A; B }
type ABC interface { AB; Bar() }
Bug: the conflict already exists in AB — before you ever reach ABC. Fix: A and B have Foo with the same signature.


Bug 5 — Implementation method conflict

type A interface { M() }
type B interface { M() }
type AB interface { A; B }   // OK 1.14+

type T struct{}
func (T) M() string { return "x" }   // signature does not match
var _ AB = T{}
Bug: Compile error — T.M() does not match interface AB's M() signature (func()). Fix: func (T) M() {} (no return value).


Bug 6 — Embed via wrong type

type X struct{ Foo() }   // ?
Bug: This is an interface, not a struct. type X interface { Foo() }.


Bug 7 — Outer override conflict

type A interface { M() string }
type B interface {
    A
    M() int   // override?
}
Bug: Compile error — same name different signature in same interface. Fix: Don't try to override — design issue.


Bug 8 — Embed in struct, but method-set issue

type A interface { Foo() }

type S struct{ A }   // embed interface

s := S{}
s.Foo()
Bug: Runtime panic — S.A == nil. The embed has no concrete type. Fix:
s := S{A: someA}


Bug 9 — Decorator forgot delegation

type Logger interface { Log(string) }

type TimestampLogger struct{ Logger }
func (t TimestampLogger) Log(msg string) {
    fmt.Println(time.Now().Format(time.RFC3339), msg)
    // Logger.Log(msg) is never called
}
Bug: No forwarding to the wrapped Logger. Output only goes to the console. Fix:
func (t TimestampLogger) Log(msg string) {
    t.Logger.Log(time.Now().Format(time.RFC3339) + " " + msg)
}


Bug 10 — Compile-time check missing

type Reader interface { Read([]byte) (int, error) }

type MyReader struct{}
// Read method is missing

var r Reader = &MyReader{}   // compile error
Bug: the compile error is only surfaced on a re-read. Improvement:
var _ Reader = (*MyReader)(nil)   // immediate compile-time check