In Go you can just ignore it and move on with the zeroed result value. Even the error the compiler gives with unused variables doesn't help since it's likely you've already used the err variable elsewhere in the function.
And there's a few cases like Print() where errors are so commonly ignored you don't even want to use the "_" ignore syntax. Go gives you the poetic license to avoid spamming underscores everywhere. error linters can be configured to handle a variety of strictness. For non-critical software, it's OK to YOLO your Print(). For human-death-on-failure software you may enforce 100% handling, not even allowing explicit ignore "_" (ie become even stricter than Rust language default)
But your editor can give some more realtime feedback instead of waiting for your tests to run, so I guess that's cool.
For example, Go's language guards against unused variables or imports, they are a compiler error. Assigning an `err` variable but not using it is a compiler error. But ignoring the error by assigning it to the reserved underscore variable name is an explicit action by the developer, just like an empty `catch` block in Java/C# or the Rust equivalent.
That is, if you choose to ignore errors, there isn't a language that will stop you. Developers should take responsibility for their own choices, instead of shift blame to the language for making it possible.
If developers were more disciplined Go wouldn't need a garbage collector because everyone would just remember to call `free()` when they're done with their memory...
It doesn't force you to do something productive with the error, but you can't act like it was what you wanted instead of an error.
I'm just a simple country gopher, but my brain isn't capable of understanding either of those things, nor are any of my coworkers, nor any of the people we hire, and it doesn't really matter how theoretically "nice" and "pure" your generics and results and monads are if us real professional programmers get confused by them.
Errors need to be explicit values, not magic monads. 'if err != nil' is good and easy to think about, 'res.map().or_else()' is incomprehensible line noise no normal programmer can understand.
https://paulgraham.com/avg.html#:~:text=The%20Blub%20Paradox
The one liner functor stuff in particular I think is a big distraction. To me the basic building block is the match statement - you match on a result, if it's Ok(T) then you get to do something with T, and if it's Err(e) then you get to do something with e. At that level it's very simple. And as far as I know (no expert though) any clever expression can be decomposed into a series of nested and possibly repetitive match statements, the apparent magic is illusory.
But I do hear you and I get the appeal of Go from that angle, obviously sticking with what you like is a good idea. Just saying Rust isn't that bad :)
Unfortunately, Go's language design also enables unused variables without any error or warning. They are only sometimes a compiler error.
Specifically, multiple return interacts poorly with unused variable detection. See:
func fallable() (int, error) {
return 0, nil
}
func f1() {
val, err := fallable()
if err != nil { panic(err) }
fmt.Println(val)
val2, err := fallable()
fmt.Println(val2)
// notice how I didn't check 'err' this time? This compiles fine
}
When you use `:=` it assigned a new variable, except when you do multiple return it re-assigns existing variables instead of shadowing them, and so the unused variable check considers them as having been used.I've seen so many ignored errors from this poor design choice, so it really does happen in practice.
I definitely have seen that, and sometimes have done that myself, but I have to say it hasn't happened in a while since the linting tools have improved
There is no language to my knowledge that prevent you from ignoring values.
Examples: Austral, some of these https://en.m.wikipedia.org/wiki/Substructural_type_system#Pr... in particular at least ATS, Alms, Granule, LinearML Though most haven't gone beyond research languages yet.