Home >Backend Development >Golang >Idiomatic way to combine these two functions into one

Idiomatic way to combine these two functions into one

王林
王林forward
2024-02-05 22:33:04699browse

Idiomatic way to combine these two functions into one

Question content

I have these two very similar functions. They each parse a specific base/bit length integer from a named query parameter. There are two functions that can handle unsigned/signed integers, you need to call strconv.ParseUint or strconv.ParseInt.

What is a concise and idiomatic way to reduce these to a single function? I feel like using interfaces (and generics?) is the way to go, but I'm not sure how to proceed.

//////////////////////////////////////////////////////////////////////

func ParseQueryParamUnsigned(name string, base int, bits int, values *url.Values) (uint64, error) {

    param := (*values)[name]

    if len(param) < 1 {
        return 0, fmt.Errorf("missing parameter %s", name)
    }

    if len(param) > 1 {
        return 0, fmt.Errorf("duplicate parameter %s", name)
    }

    v, err := strconv.ParseUint(param[0], base, bits)

    if err != nil {
        return 0, fmt.Errorf("bad value for '%s' (%s)", name, err.Error())
    }
    return v, nil
}

//////////////////////////////////////////////////////////////////////

func ParseQueryParamSigned(name string, base int, bits int, values *url.Values) (int64, error) {

    param := (*values)[name]

    if len(param) < 1 {
        return 0, fmt.Errorf("missing parameter %s", name)
    }

    if len(param) > 1 {
        return 0, fmt.Errorf("duplicate parameter %s", name)
    }

    v, err := strconv.ParseInt(param[0], base, bits)

    if err != nil {
        return 0, fmt.Errorf("bad value for '%s' (%s)", name, err.Error())
    }
    return v, nil
}

Correct answer


You can make a universal parser like this:

func ParseQueryParam[T any](name string, values url.Values, parser func(string) (T,error)) (T, error) {

    param := values[name]

    if len(param) < 1 {
        return 0, fmt.Errorf("missing parameter %s", name)
    }

    if len(param) > 1 {
        return 0, fmt.Errorf("duplicate parameter %s", name)
    }

    v, err := parser(param[0])

    if err != nil {
        return 0, fmt.Errorf("bad value for '%s' (%s)", name, err.Error())
    }
    return v, nil
}

and use it as:

value, err:=ParseQueryParam[int64]("param",values, func(s string) (int64,error) {
  return strconv.ParseInt(s,10,64)
})

The above is the detailed content of Idiomatic way to combine these two functions into one. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete