> The best practice is pointer errors.

If that is an accepted best practice, wouldn't it make sense to have a go 
vet or linter check that verifies that (at least for public error types)?
It is really not visible from the api and developers will only start 
thinking about it once they have been bitten.

Imho this needs much better tooling.

On Wednesday, February 12, 2025 at 10:06:08 AM UTC+1 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/7fd760d4-acce-4562-9ded-defa180f5c18n%40googlegroups.com.

Reply via email to