It's also consistent with the common idiom of errors.New("foo") which 
returns a pointer (to an unexported type) - although this doesn't appear to 
be documented, except that "Each call to New returns a distinct error value 
even if the text is identical"

On Wednesday, 12 February 2025 at 09:06:08 UTC Axel Wagner wrote:

> On Wed, 12 Feb 2025 at 09:21, cpu...@gmail.com <cpu...@gmail.com> wrote:
>
>> I've had some ongoing confusion about using errors.As (see 
>> https://play.golang.com/p/m4_cXCzOViD). The issue I'm having is this 
>> part of the contract:
>>
>> > An error matches target if the error's concrete value is assignable to 
>> the value pointed to by target
>>
>> I always expected (yes, I know), that base and pointer receivers are 
>> interchangeable. This is not the case (see playground). This seems to make 
>> using it error-prone as you'll always need to carefully think about the 
>> return type of the function invoked. While the contract is always error, a 
>> function may return a base or a pointer error type. This influences how 
>> using errors.As must be done.
>>
>> Are there best practices for:
>> - return base vs. pointer errors
>>
>
> The best practice is pointer errors. I would have personally preferred to 
> live in a world where value errors are better (in particular, it would be 
> pretty nice to be able to compare full error values using `==` in tests). 
> But the issue you have discovered is pretty much exactly, why pointer 
> errors are better.
>
> If you declare `Error()` on a value receiver, then both `err.(YourErr)` 
> and `err.(*YourErr)` will compile just fine, as value-methods are promoted 
> to the pointer type. But only one of them will succeed. Similarly, both 
> `return YourErr{…}` and `return &YourErr{…}` will compile. So it is 
> somewhat easy to make a mistake that are then hard to debug in practice - 
> and the error paths tend to be badly tested already.
>
> If, on the other hand, you declare it with a pointer receiver, only 
> `err.(*YourErr)` and `return &YourErr{…}` will compile. Meaning the 
> compiler ensures that you write the correct code.
>
> errors.As is ultimately a dynamic extension of this semantic difference, 
> which is the problem you have stumbled on.
>  
>
>> - crafting  the errors.As target type without inspecting the actual 
>> function invoked
>>
>> ...and could it make sense to lessen errors.As to match pointer with 
>> non-pointer receivers?
>>
>> Thanks! 
>>
>> -- 
>> 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...@googlegroups.com.
>> To view this discussion visit 
>> https://groups.google.com/d/msgid/golang-nuts/afe2df8a-9e42-4511-abe6-8e03b906d637n%40googlegroups.com
>>  
>> <https://groups.google.com/d/msgid/golang-nuts/afe2df8a-9e42-4511-abe6-8e03b906d637n%40googlegroups.com?utm_medium=email&utm_source=footer>
>> .
>>
>

-- 
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 visit 
https://groups.google.com/d/msgid/golang-nuts/98375669-c29b-4d06-bf79-04c548aada46n%40googlegroups.com.

Reply via email to