Parsing with strconv
Everything that arrives from outside a program - a flag, an environment
variable, a form field, a line of CSV - arrives as a string. Turning it into a
number or a boolean is the strconv package's
job, and every function in it returns two values: the parsed result and an
error.
n, err := strconv.Atoi("42") // 42, nil
f, err := strconv.ParseFloat("1.5", 64) // 1.5, nil
b, err := strconv.ParseBool("true") // true, nil
Atoi is shorthand for ParseInt(s, 10, 0).
Going the other way is strconv.Itoa(n),
FormatFloat, FormatBool.
Two things catch people out. First, these functions are strict: no
surrounding whitespace, no trailing junk. strconv.Atoi(" 42 ") is an error, so
a strings.TrimSpace usually comes
first. Second, the error is not a bare message. It is a
*strconv.NumError holding the function
name, the input, and one of two sentinel errors:
_, err := strconv.Atoi("abc")
errors.Is(err, strconv.ErrSyntax) // true - it was not a number at all
_, err = strconv.Atoi("999999999999999999999999")
errors.Is(err, strconv.ErrRange) // true - it was a number, but too big
That is why a parse error is worth passing along unchanged: rewrite it with your
own fmt.Errorf message and the caller can no longer tell "not a number" from
"too large".
The other habit worth building is the Or wrapper. Configuration usually
has a default, and
func ParseIntOr(s string, fallback int) int
turns a two-value call into a one-value one at the single place that knows what the default is.
Task
Fill in the six functions in main.go.
ParseIntOr,ParseFloatOrandParseBoolOrparse a trimmedsand fall back when it does not parse.SumFields(csv)adds up comma-separated integers, skipping empty fields, and on the first bad field returns0and strconv's own error.ParseKeyValues(s)reads"a=1,b=2"into amap[string]int.JoinInts(nums)renders a slice back into"1,2,3".
Hints
strings.TrimSpacebefore every parse, not after.- Return the error from
strconvdirectly. The test useserrors.Is(err, strconv.ErrSyntax)anderrors.Is(err, strconv.ErrRange), so wrapping it in a message of your own with%vwould break the link. strings.Cut(entry, "=")returns the part before, the part after, and whether the separator was there at all - a better fit thanstrings.Splitwhen there is exactly one separator to find.ParseKeyValuesmust return a non-nil map for an input with no entries, andnilalongside an error.strconv.Itoais the fast path forint.fmt.Sprintf("%d", n)gives the same string and does much more work to get there.