5 ms·
I officially proposed this recently and it wasn’t well received: https://github.com/golang/go/issues/56165 https://github.com/golang/go/issues/56165 The propos
by gregwebs 4y ago
I officially proposed this recently and it wasn’t well received: https://github.com/golang/go/issues/56165 https://github.com/golang/go/issues/56165
The proposal the submitted article references has been inactive for years.
After submitting proposals and looking at the existing ones and thinking about this more I think the biggest problem with error verbosity is just that you have to also return zero values for the success results when all you want to do is return an error. This obfuscates the intent, making things harder to read and write. In some scenarios such as adding an additional return result it forces changes on multiple unrelated lines when it should just be a single-line change.
It's also possible that errors wouldn't be as verbose if Golang had automatic error tracing like Zig (a slightly better form of stack traces)- in that case the need for error annotations would decrease. With that and zero values removed, just allowing the error return on a single line instead of 3 might be all that is needed.
if err != nil { return err }
- pornel 4y agoSingle line reduces noise, but doesn't make it less cumbersome. My pet peeve is that when error types differ, I need to juggle between `err` and `err2`. When I refactor code and add/remove fallible functions, I need to change between `=` and `:=` accordingly only because the error has to get a named variable every time.
- im-a-baby 4y agoGenerally, returning a typed error in the function signature in Go is very annoying and dangerous. An example why: import "fmt" type MyError struct{} func (m *MyError) Error() string { return "" } func myFunc() *MyError { return nil } func main() { var err error err = myFunc() if err == nil { fmt.Println("No Error") } else { fmt.Println("Error") // This prints } }
- svnpenn 4y agothats kind of misleading, as you could just do: func myFunc() error
- im-a-baby 4y agoYes you could do that, but then you’d lose type info on the error.
- gregwebs 4y agoI agree this is awful, but isn't it solved here by not using pointers? I don't remember coming across a case where a custom error type benefited from being a pointer. I am sure such a case exists, but then such a case should be used when giving example code.
- im-a-baby 4y agoNo not using pointers would not solve the issue. The issue is that the specific error implementation type is part of the method signature. If you returned type MyError instead of *MyError, then it would be impossible to return nil from the method because only pointers can be nil.
- gregwebs 4y agoI get that. But why define the Error method on a pointed receiver? In my experience almost all errors can be immutable particularly once you start using wrapping.
- gregwebs 4y agoNever mind- that doesn't actually make a difference. The solution in this case is to not re-use an existing error variable- but re-use of an error variable is common practice.
- im-a-baby 4y agoYea, the issue is that nil's in Go are typed. So `err == nil` is checking err against error's nil value, but the value stored in err is *MyError's nil value. package main import "fmt" type MyError struct{} func (m *MyError) Error() string { return "" } func main() { var err error = nil var myErr *MyError = nil fmt.Println(err == myErr) // this is false }
- gregwebs 4y ago
- infogulch 4y agoCouldn't they solve this by letting you rebind/shadow `err` without requiring a new block? Then to make sure you don't accidentally ignore the error, the standard unused variables compile error would prevent that (it would right? it could at least).
- deleted 4y ago[deleted]
- svnpenn 4y ago> all you want to do is return an error Nope. This isn't even true in all situations. For a simple example, just look at description of the extremely popular io.Reader: > An instance of this general case is that a Reader returning a non-zero number of bytes at the end of the input stream may return either err == EOF or err == nil. https://godocs.io/io#Reader https://godocs.io/io#Reader
- the_gipsy 4y agoIn 99% of situations you do not check the error type nor the value, like io.Reader.
- tommiegannert 4y ago> I think the biggest problem with error verbosity is just that you have to also return zero values for the success results I agree, and this got worse with generics since T{} doesn't work, and we have to use *new(T), which is quirky. However, I wonder if we just want an Optional/Maybe type that has support for multiple values. Without variadic/recursive generics, we'd need compiler support. But a tagged union would get rid of the zero-values. (I somewhat agree about the io.Reader case where returning both the number of "screwed up" bytes and an error can be useful, though perhaps the number of bytes should be encoded in the error type instead. I rarely care about them.)
- masklinn 4y ago> (I somewhat agree about the io.Reader case where returning both the number of "screwed up" bytes and an error can be useful, though perhaps the number of bytes should be encoded in the error type instead. I rarely care about them.) Or you can just keep it as-is because it's one of the very few cases where it does make sense to have a product type.
- the_gipsy 4y agoWell if you add sugar for errors, and as sugary as "specific to the error type as the last element of a return type, plus automatic zero values", then just make it like rust's `?` already.
- mikelward 4y agoThis would be easier if there was an easy way to write the zero value, irrespective of type. https://github.com/golang/go/issues/19642 https://github.com/golang/go/issues/19642 was a proposal to have e.g. return _, _, err as an alternative to e.g. return 0, "", err
- gregwebs 4y agoI would prefer this to the status quo, but it isn't a completely clean solution to the problem. If I now make a one line change at the bottom of my function to return one additional result, the only additional change in the diff should be to the type signature. But now my diff will still show adding zero values on all the rest of the return lines. It's nice that they will only be underscores- again it is certainly better than the status quo.