Is return nil, nil not idiomatic go?
Asked Answered
V

2

6

If we have the following method in GO:

GetCustomer(id string) (*Customer, error)

A customer for a given id may not exist in DB. When a customer is not found, the code can

return nil, nil

Is this considered bad coding practice in Go? Or would the idiomatic Go code would look like

 return nil, errCustomerNotFound

The problem I see with the second approach is that you end up checking for this specific error and handling it seperately.

Are there examples in Go source or libraries where this situation arises and one of the approaches is preferred?

Update

If return nil, nil is considered as not idiomatic. I was wondering why that is true in this case? As *Customer is a pointer, I want to return nil to indicate absence of value

Velarde answered 17/7, 2020 at 5:57 Comment(11)
A third option would be to have the signature GetCustomer(id string) (c *Customer, ok bool, err error) and use the return return nil, false, nil. This is similar to getting a key from a map in which that key may or may not exist.Ewers
Yeah sure, but is return nil, nil considered bad?Velarde
I don't think there's any problem with returning nil. I think the other two options are more explicit, but if you and your team agree on returning nil in these sorts of cases I think it's no problem. Or if you're writing a public library then document that you return nil and keep it consistent if you have any other Get* functions.Ewers
For this specific example, returning a "not found" error is the common sense approach. "The problem I see with the second approach is that you end up checking for this specific error and handling it seperately." This is not a real problem, there are many cases where a function can return different errors that need to be handled differently by the caller, also it is not always the case, many callers may not care that the error is specifically "not found" and just check for non-nilness.Airway
... If you have a case where a function's primary return value can be nil even if no error occurred, you should mention that as clearly as possible in the documentation of that function.Airway
... and yes, return nil, nil is not idiomatic Go.Airway
any references for why return nil, nil is not idiomatic, would like to know why it considered not idiomaticVelarde
@MuffinTop I did not understand "distinguished primary return values" could you please explain?Velarde
Let me rephrase that: The Go standard library does not use a sentinel value in the first return value to indicate "not found" errors. In your first example, the sentinel value is nil.Betjeman
Why is return nil,nil not idiomatic, specifically in this case? As it is a pointer, I want to return nil to indicate absence of valueVelarde
The problem I see with the second approach is that you end up checking for this specific error and handling it seperately. use a standard error like sql.ErrNotFound (or similar). That the not found value is a customer, is a detail useful for logging, within your code, most of the time, there should be enough context to figure out that it was a customer.Carrizales
N
12

Whether return nil, nil is idiomatic in your case or not depends on whether a nil *Customer is a useful value.

If a nil value for *Customer is a normal, useful value in your code, then returning that, with no error, makes sense.

It would be rare that a nil struct pointer is useful, though--that alone could be considered non-idiomatic in most cases.

The rule to follow:

Every function should always return a useful set of values.

In your case, where you return a struct pointer and an error, one could reasonably assume that at most one of those would be nil.

Using a nil struct pointer to indicate the absence of a value can be idiomatic, but not in conjunction with an error. If your function can have only a single error condition of 'not found', you might opt for a function that returns only a single value, which may be nil, or you may opt to return a boolean indicating existence rather than an error.

But returning a nil to mean "not found" when also including an error is confusing, at best, because it violates the principle of least astonishment.

Nonlinearity answered 17/7, 2020 at 6:53 Comment(2)
@nmdr the presence of an error indicates that the primary return value is invalid and should not be used as intended, the absence of an error, in most cases, will indicate the inverse. This may not always be the case but it is common practice, so much so that I would call it idiomatic. Most Go programmers, I would assume, will be used to, and rely on, this common practice to not have to double-check the primary value for nil-ness before they can use it as intended if they've already checked the error for nil, and because of that they would be tripped up by an api like yours.Airway
Why is absence of a value an error? In my case it's not and is expected. Returning it as an error would be a bigger astonishment.Encephalomyelitis
T
0

It varies case by case, sometimes nil values are useful in cases where empty returns are frequent and useful as a zero value, where the rest of your code behaves well with them.

If nil values are uncommon and difficult to catch in testing, you should never return them at all. Also, returning a nil channel, or anything that someone may want to pass to a function as an interface value or which may lead to confusing nil pointers with nil interfaces, is very heavily discouraged.

Tawnatawney answered 13/3 at 10:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.