转到如何检查产品类型


I have model Product with field Type.
Something like this:

type ProductType string

var (
    PtRouteTransportation    ProductType = "ProductRT"
    PtOnDemandTransportation ProductType = "ProductDT"
    PtExcursion              ProductType = "ProductEX"
    PtTicket                 ProductType = "ProductTK"
    PtQuote                  ProductType = "ProductQT"
    PtGood                   ProductType = "ProductGD"
)

type Product struct {
    ...
    Type ProductType
    ...
}

In Create function I have type form param:

type := req.Form.Get("type")


Question: how to check is type valid?

Simplest way is:

if type != PtRouteTransportation && type != PtOnDemandTransportation && ...

but what I supposed to do if Product will have 100 types?

How to do this in go way?

Really the simplest is to use a map, not as fast as constants but if if you have to test against a large set, it's the most convenient way.

Also since it's pre-allocated, it's thread-safe, so you won't have to worry about locks, unless you add to it at runtime.

var (
    ptTypes = map[string]struct{}{
        "ProductRT": {},
        "ProductDT": {},
        "ProductEX": {},
        "ProductTK": {},
        "ProductQT": {},
        "ProductGD": {},
    }

)

func validType(t string) (ok bool) {
    _, ok = ptTypes[t]
    return
}

Instead of using a type alias to a basic type, why not using a type alias to a private type (meaning a struct you cannot initialize outside your package)

See this example.

type ProductType productType

type productType struct {
    name string
}

var (
    PtRouteTransportation    ProductType = ProductType(productType{"ProductRT"})
    PtOnDemandTransportation ProductType = ProductType(productType{"ProductDT"})
    PtExcursion              ProductType = ProductType(productType{"ProductEX"})
    PtTicket                 ProductType = ProductType(productType{"ProductTK"})
    PtQuote                  ProductType = ProductType(productType{"ProductQT"})
    PtGood                   ProductType = ProductType(productType{"ProductGD"})
)

func printProductType(pt ProductType) {
    fmt.Println(pt.name)
}
func main() {
    fmt.Println("Hello, playground")
    // printProductType("test") // cannot use "test" (type string) as type ProductType in argument to printProductType
    printProductType(PtRouteTransportation)
}

It means you cannot use any other values than the public ones defined in the var section.

If you manage to pass a value to the printProductType(pt ProductType), your value is always a valid one.


For the dynamic checking part, that OneOfOne addresses in his answer, I would add a function GetProductType(name string) ProductType which:

  • check if the name is a valid one
  • return one of the official ProductType instances defined in the var section above.

That way, the rest of your code always work with an official ProductType value (and not with a 'string' which happens to be matching the right value)