IssueRaiser

proposal: spec: require return values to be explicitly used or ignored (Go 2)

Today, if a Go function returns both a value and an error, the user must either assign the error to a variable ```go v, err := computeTheThing() ``` or explicitly ignore it ```go v, _ := computeTheThing() ``` However, errors that are the only return value (as from `io.Closer.Close` or [`proto.Unmarshal`](https://godoc.org/github.com/golang/protobuf/proto#Unmarshal)) or paired with an often-unneeded return value (as from `io.Writer.Write`) are easy to accidentally forget, and not obvious in the code when forgotten. ```go tx.Commit() // Store the transaction in the database! ``` The same problem can occur even when errors are not involved, as in functional-style APIs: ```go t := time.Now() t.Add(10 * time.Second) // Should be t = t.Add(…) ``` ```go strconv.AppendQuote(dst, "suffix") // Should be dst = strconv.AppendQuote(…) ``` For the few cases where the user really does intend to ignore the return-values, it's easy to make that explicit in the code: ```go _, _ = fmt.Fprintln(&buf, v) // Writes to a bytes.Buffer cannot fail. go func() { _, _ = fmt.Fprintln(os.Stderr, findTheBug()) }() ``` And that transformation should be straightforward to apply to an existing code base (e.g. in a Go 1-to-2 conversion). On the other hand, the consequences of a forgotten error-check or a dropped assignment can be quite severe (e.g., corrupted entries stored to a production database, silent failure to commit user data to long-term storage, crashes due to unvalidated user inputs). ---

Posted by bcmills on Jun 26, 2017, 8:01 PM

Tags

Related issues

Raise real-world problems, find people facing the same issue, and discuss solutions.4,500 issues0 comments

reliability (Software)

proposal: spec: require return values to be explicitly used or ignored (Go 2)

bcmillsJun 26, 2017, 8:01 PM

Today, if a Go function returns both a value and an error, the user must either assign the error to a variable ```go v, err := computeTheThing() ``` or explicitly ignore it ```go v, _ := computeTheThing() ``` However, errors that are the only return value (as from `io.Closer.Close` or [`proto.Unmarshal`](https://godoc.org/github.com/golang/protobuf/proto#Unmarshal)) or paired with an often-unneeded return value (as from `io.Writer.Write`) are easy to accidentally forget, and not obvious in the code when forgotten. ```go tx.Commit() // Store the transaction in the database! ``` The same problem can occur even when errors are not involved, as in functional-style APIs: ```go t := time.Now() t.Add(10 * time.Second) // Should be t = t.Add(…) ``` ```go strconv.AppendQuote(dst, "suffix") // Should be dst = strconv.AppendQuote(…) ``` For the few cases where the user really does intend to ignore the return-values, it's easy to make that explicit in the code: ```go _, _ = fmt.Fprintln(&buf, v) // Writes to a bytes.Buffer cannot fail. go func() { _, _ = fmt.Fprintln(os.Stderr, findTheBug()) }() ``` And that transformation should be straightforward to apply to an existing code base (e.g. in a Go 1-to-2 conversion). On the other hand, the consequences of a forgotten error-check or a dropped assignment can be quite severe (e.g., corrupted entries stored to a production database, silent failure to commit user data to long-term storage, crashes due to unvalidated user inputs). ---

Comments (0)

No comments yet. Start the discussion.

Comment on this issue