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.

Reply via email to