Thanks again - I'm learning a lot here!
For info, the background here is that I've been writing code like:
type T struct {
SomeField int
}
func NewTFromJSON(data []byte) (*T, error) {
var t T
return &t, json.Unmarshal(data, &t)
}
which wraps up error handling into a single line. This works when T is a non-simple type as &t does not change, even if the value of t does.
Writing this with T being a simple type, like int, results in the case described in the original post:
// NewIntFromJSON relies on undefined behavior, don't use it!
func NewIntFromJSON(data []byte) (int, error) {
var i int
return i, json.Unmarshal(data, &i)
}
So, in these cases I will do as Axel suggests and avoid the implicit dependence on evaluation order.
A go vet check for this would be wonderful, even if it's not perfect. As long as there aren't any false positives (i.e. warning when the code does not in fact rely on unspecified behavior), it matters less if there are false negatives (i.e. not warning when the code actually relies on unspecified behavior). Maybe a simple test could catch the most common cases.