Many Go APIs return a useful value and an error. A nil error signals success;
a nonnil error means the caller must follow the API's failure policy before
using the other result. This is more explicit than ordinary Python exception
propagation and differs from C++ stack unwinding. It also makes it easy to
accidentally ignore a failure if you discard the error with _. Reserve that
choice for cases where the contract really makes failure irrelevant.
The lesson's parser returns (0, err) on failure. That does not make every
zero a failure: parsing the string "0" returns (0, nil). Read both results.
Validate range after parsing because syntactically valid decimal text can still
be outside the application's accepted domain. The standard parser also reports
values too large for int; do not treat its numeric return as successful data.
Preserve a cause while adding context
A sentinel created with errors.New can name a public failure category. A batch
operation may add which item failed. Use fmt.Errorf with %w to retain the
cause, and errors.Is to ask whether a wrapped error matches the category.
Exact string comparison couples callers to messages intended for people.
Wrapping is part of an API decision: exposing a cause lets callers depend on it.
package main
import ("errors"; "fmt")
func main() {
invalid := errors.New("invalid count")
wrapped := fmt.Errorf("count 2: %w", invalid)
printed := fmt.Errorf("count 2: %v", invalid)
fmt.Println(errors.Is(wrapped, invalid), errors.Is(printed, invalid))
}The text of the two errors looks alike, but the output is true false.
Wrapping preserves an inspectable chain. Creating a new errors.New with the
same message also creates a different sentinel identity.
Decide whether partial work may escape
TotalCounts promises all-or-nothing output. It can accumulate internally while validating, but any failure returns zero, not the current sum. Other APIs can legitimately return partial work alongside an error; that must be stated and tested separately. Error handling is a data contract, not a universal rule to throw away every partial result in every program.
For ordinary invalid user input, return an error rather than panic. A panic indicates a different control-flow mechanism and is not the expected path for a malformed count. Library code also should not terminate the process to announce a parse error; the caller decides how to render it and what exit status a command should use.
Practice successful zero, trimmed input, a fractional string and an oversized integer. The fill preserves the error cause at the batch boundary. The bugs respectively reject a valid boundary and lose identity while retaining text. The tests inspect errors.Is and the documented position without prescribing every word of an error message.