As sad as it sounds, inside of me I agree on "it is all moot anyway", but... Aren't we allowed to at least freely day-dream anyway :) ?
I was thinking about it over weekend, and came with these "rules", but I need help on these for sure
- If expression ends with ? (like func()?) , then it works as return in "if a, err := func(); err != nil { return a, err }"
- If it is in the middle of expression ...
- without error handled
val := func()?.somethingElse().member
then it just expanded to a
val := (type(member))nil
if tmp, err := func(); tmp == nil || err != nil {
val = tmp.somethingElse().member
}
just saving the embarrassment of nil pointer dereference.
- with an error on the left side
val, err := func()?.somethingElse()
then it is expanded to
val := (type(somethingElse())nil
var err error
if tmp, err := func(); if err == nil && tmp != nil {
val, err = tmp.somethingElse()
}
- If error manipulation required - use a regular "if err != nil { return _, wrap(err, "bad thing happen") }
I am probably overthinking it at this point (and it is way past bedtime), but maybe it might make sense to have 2 different constructs - one for nil-guard "?" and one for "check for nil AND error", thus becoming "??"
With that logic above, the following should make some sense
type Mood interface {
frolic()
avoided() Mood
passed() (Mood, error)
}
func getMood() (Mood, error) {...}
func usage1() (Mood, error) {
return getMood()??.passed()
}
func usage2() error {
return getMood()??.passed()
}
func usage3() interface{} {
return getMood()?.avoided()
}
func usage4() (interface{}, error) {
mood := getMood()?? /// will short-circuit if getMood() returns an error
return mood?.passed() // guard for mood == nil; but will return no error in that case either since it will be nil
}
Andrey