unknwon/the-way-to-go_ZH_CN · error
I won't be able to do a sqrt of negative number!
Error message
I won't be able to do a sqrt of negative number!
What it means
Error returned by MySqrt in the Chapter 6 exercise demonstrating the unnamed (value, error) return style. A real square root is undefined for negative arguments, so for f < 0 the function returns (math.NaN(), errors.New(...)) instead of a silent NaN. It teaches reporting an invalid domain through the error result rather than panicking or returning only a magic value.
Source
Thrown at eBook/exercises/chapter_6/error_returnval.go:33
} else {
fmt.Println("It's ok! Return values are: ", ret1, err1)
}
fmt.Print("Second example with 5: ")
//you could also write it like this
if ret2, err2 := MySqrt(5); err2 != nil {
fmt.Println("Error! Return values are: ", ret2, err2)
} else {
fmt.Println("It's ok! Return values are: ", ret2, err2)
}
// named return variables:
fmt.Println(MySqrt2(5))
}
func MySqrt(f float64) (float64, error) {
//return an error as second parameter if invalid input
if f < 0 {
return float64(math.NaN()), errors.New("I won't be able to do a sqrt of negative number!")
}
//otherwise use default square root function
return math.Sqrt(f), nil
}
//name the return variables - by default it will have 'zero-ed' values i.e. numbers are 0, string is empty, etc.
func MySqrt2(f float64) (ret float64, err error) {
if f < 0 {
//then you can use those variables in code
ret = float64(math.NaN())
err = errors.New("I won't be able to do a sqrt of negative number!")
} else {
ret = math.Sqrt(f)
//err is not assigned, so it gets default value nil
}
//automatically return the named return variables ret and err
return
}View on GitHub (pinned to 7a54d34d36)
Solutions
- Validate the domain before calling: if f >= 0 { r, _ := MySqrt(f) } else { reject the input }
- If negative inputs are legitimate for your use case, switch to complex square roots: import math/cmplx and use cmplx.Sqrt(complex(f, 0))
- Check the error at the call site and include f in the message — NaN silently poisons later arithmetic and comparisons
- Clamp tiny negatives produced by rounding: if math.Abs(f) < 1e-12 { f = 0 } before the call
Example fix
// before
r, _ := MySqrt(delta) // delta = -1e-9 from rounding; r is NaN, poisons downstream math
// after
r, err := MySqrt(delta)
if err != nil {
return fmt.Errorf("MySqrt(%g): %v", delta, err)
} Defensive patterns
Strategy: validation
Validate before calling
if f < 0 {
return 0, fmt.Errorf("invalid argument %g: sqrt requires f >= 0", f)
}
return MySqrt(f) Try / catch
r, err := MySqrt(x)
if err != nil {
return fmt.Errorf("MySqrt(%g): %v", x, err)
}
// r is a real number here Prevention
- Validate numeric domains at the system boundary (CLI args, HTTP payload, file parser) before math runs
- Treat NaN results as bugs: assert !math.IsNaN(r) after err == nil in tests
- For mathematically non-negative intermediates (sums of squares), clamp tiny negative float drift to 0
- If negatives are valid input, use math/cmplx.Sqrt instead of widening this error's meaning
When it happens
Trigger: Calling MySqrt with any negative float64 (e.g. MySqrt(-1)): the guard if f < 0 fires before math.Sqrt is reached. The demo main only calls MySqrt(5), so seeing this error means your own code (or your edit of the exercise) passed a negative value.
Common situations: Computing distances from deltas that can go negative through float rounding; feeding user-supplied numbers (variance, sum of squares) straight into sqrt; porting formulas whose intermediates are theoretically non-negative but drift below zero numerically; deliberately calling with -1 to test the error branch as the book's commented output shows.
Related errors
- things aren’t good
- expected GET
- math: square root of negative number %g
- %g is out of the int32 range
- "ERROR occurred:" + err.Error()
AI-assisted analysis of unknwon/the-way-to-go_ZH_CN@7a54d34d36 (2026-08-15).
Data as JSON: /api/errors/66ef45d22b322640.
Report an issue: GitHub.