-1

In order to actually change struct fields in a method, you need a pointer-type receiver. I understand that.

Why can't I satisfy the io.Writer interface with a pointer receiver so that I can make changes to struct fields? Is there an idiomatic way to do this?

// CountWriter is a type representing a writer that also counts
type CountWriter struct {
    Count      int
    Output     io.Writer
}

func (cw *CountWriter) Write(p []byte) (int, error) {
    cw.Count++
    return cw.Output.Write(p)
}

func takeAWriter(w io.Writer) {
    w.Write([]byte("Testing"))
}

func main() {
    boo := CountWriter{0, os.Stdout}
    boo.Write([]byte("Hello\n"))
    fmt.Printf("Count is incremented: %d", boo.Count)
    takeAWriter(boo)
}

The code yields this error:

prog.go:27:13: cannot use boo (type CountWriter) as type io.Writer in argument to takeAWriter:
    CountWriter does not implement io.Writer (Write method has pointer receiver)

It seems you can either satisfy the Writer interface or have your changes made to the actual struct. If I change the Write method to a value receiver (func (cw CountWriter) Write...), I can avoid the error but the value does not increment. :(

https://play.golang.org/p/pEUwwTj0zrb

DarkerIvy
  • 1,477
  • 14
  • 26
  • 1
    You declared `Write()` to have pointer receiver, so use a pointer value: `boo := &CountWriter{0, os.Stdout}`. See: [Go, X does not implement Y (… method has a pointer receiver)](https://stackoverflow.com/questions/40823315/go-x-does-not-implement-y-method-has-a-pointer-receiver/40824044#40824044). – icza Sep 10 '18 at 15:24
  • 1
    Indeed, as icza points out, it's not that you can't satisfy the interface with a pointer receiver, it's that only a `*CounterWriter` satisfies the interface (because of the pointer receiver) while a `CounterWriter` does not. – Adrian Sep 10 '18 at 15:27
  • Very nice! I misunderstood what was causing the error (not the satisfaction). – DarkerIvy Sep 10 '18 at 15:37

1 Answers1

0

boo Doesn’t implement the interface because Write takes *CountWriter and not a CountWriter
However, &boo will be accepted by Write, so you have to pass it instead.

Daniel
  • 30,896
  • 18
  • 85
  • 139