On Wed, Nov 13, 2019 at 9:24 AM Brian Candler <b.cand...@pobox.com> wrote: > > In https://blog.golang.org/error-handling-and-go, it shows the well-known > error interface: > > type error interface { > Error() string > } > > and it gives an example of a user-defined error: > > // errorString is a trivial implementation of error. > type errorString struct { > s string > } > > func (e *errorString) Error() string { > return e.s > } > > // New returns an error that formats as the given text. > func New(text string) error { > return &errorString{text} > } > > I notice that it's returning a pointer to an error object. My question is: > is there a particular reason for returning a pointer here, rather than a > direct instance of an error? > > The word "pointer" doesn't appear anywhere in that blog posting. Clearly a > pointer allows the possibility of returning "nil" - but an interface variable > can have a nil value too. Without the pointers, it becomes: > > func (e errorString) Error() string { > return e.s > } > > func New(text string) error { > return errorString{text} > } > > and this appears to work the same - see a longer example on play (based on > someone else's example, but I just removed the pointers). > > I'm aware that the method set of *T includes the methods of T, so a pointer > functions perfectly well in place of a concrete value to implement an > interface. Also, passing a pointer might be slightly more efficient, in that > it reduces a bit of copying. Other than that, is there a reason why code > should return pointers to error objects rather than error objects? > > I did try looking through the FAQ, which asks "Should I define methods on > values or pointers?" (although not "should I return values or pointers?"), > and ends up by saying: > > For types such as basic types, slices, and small structs, a value receiver is > very cheap so unless the semantics of the method requires a pointer, a value > receiver is efficient and clear. > > Which makes me wonder if I'm missing some other reason for using pointers in > this context.
That code could have used a value rather than a pointer. I didn't write it, but I would guess at two possible reasons for using a pointer. First, in practice most interfaces are used to hold pointer values. This is not quite the same as whether a method should be defined on a (non-pointer) value or a pointer. The question here is whether, when converting a value to an interface type, one should convert a (non-pointer) value or a pointer. In practice most people use pointers. Not because non-pointer values don't work, but just because it's a common style. Second, and perhaps the reason the style has developed this way, the current implementation of interfaces is that they always store pointer values. If you store a non-pointer value in an interface, that value is copied into memory, and a pointer to that memory is stored in the interface. So in effect storing a pointer value writes out what the implementation is doing anyhow. And then when you call a method, the code is a tiny bit more efficient if it's a pointer method, since you can just pass the pointer from the interface rather than copying the value. These aren't particularly good reasons, since the efficiency cost is likely unmeasurable outside of micro-benchmarks, but they probably feed into the general style. Ian -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CAOyqgcUi6W8LJo1Xm5DqxQfVJNvUd%3DJdek_3OSXrpRujeU7HsQ%40mail.gmail.com.