{"record":{"id":"66ef45d22b322640","repo":"unknwon/the-way-to-go_ZH_CN","slug":"i-won-t-be-able-to-do-a-sqrt-of-negative-number","errorCode":null,"errorMessage":"I won't be able to do a sqrt of negative number!","messagePattern":"I won't be able to do a sqrt of negative number!","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"eBook/exercises/chapter_6/error_returnval.go","lineNumber":33,"sourceCode":"\t} else {\n\t\tfmt.Println(\"It's ok! Return values are: \", ret1, err1)\n\t}\n\n\tfmt.Print(\"Second example with 5: \")\n\t//you could also write it like this\n\tif ret2, err2 := MySqrt(5); err2 != nil {\n\t\tfmt.Println(\"Error! Return values are: \", ret2, err2)\n\t} else {\n\t\tfmt.Println(\"It's ok! Return values are: \", ret2, err2)\n\t}\n\t// named return variables:\n\tfmt.Println(MySqrt2(5))\n}\n\nfunc MySqrt(f float64) (float64, error) {\n\t//return an error as second parameter if invalid input\n\tif f < 0 {\n\t\treturn float64(math.NaN()), errors.New(\"I won't be able to do a sqrt of negative number!\")\n\t}\n\t//otherwise use default square root function\n\treturn math.Sqrt(f), nil\n}\n\n//name the return variables - by default it will have 'zero-ed' values i.e. numbers are 0, string is empty, etc.\nfunc MySqrt2(f float64) (ret float64, err error) {\n\tif f < 0 {\n\t\t//then you can use those variables in code\n\t\tret = float64(math.NaN())\n\t\terr = errors.New(\"I won't be able to do a sqrt of negative number!\")\n\t} else {\n\t\tret = math.Sqrt(f)\n\t\t//err is not assigned, so it gets default value nil\n\t}\n\t//automatically return the named return variables ret and err\n\treturn\n}","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/unknwon/the-way-to-go_ZH_CN/blob/7a54d34d3657084b6a59e5618bd069b912d571aa/eBook/exercises/chapter_6/error_returnval.go#L15-L51","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nr, _ := MySqrt(delta) // delta = -1e-9 from rounding; r is NaN, poisons downstream math\n\n// after\nr, err := MySqrt(delta)\nif err != nil {\n\treturn fmt.Errorf(\"MySqrt(%g): %v\", delta, err)\n}","handlingStrategy":"validation","validationCode":"if f < 0 {\n\treturn 0, fmt.Errorf(\"invalid argument %g: sqrt requires f >= 0\", f)\n}\nreturn MySqrt(f)","typeGuard":null,"tryCatchPattern":"r, err := MySqrt(x)\nif err != nil {\n\treturn fmt.Errorf(\"MySqrt(%g): %v\", x, err)\n}\n// r is a real number here","preventionTips":["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"],"tags":["go","math","domain-error","error-handling"],"backgroundTag":null,"analyzedSha":"7a54d34d3657084b6a59e5618bd069b912d571aa","analyzedAt":"2026-08-15T15:13:06.026Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}