如何检查产品的类型

huangapple go评论76阅读模式
英文:

Go How to check type of product

问题

我有一个名为Product的模型,其中包含一个字段Type

类似这样的代码:

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
    // ...
}

Create函数中,我有一个名为type的表单参数:

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

问题:如何检查type是否有效?

最简单的方法是:

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

但是如果Product有100种类型,我该怎么办?

go中如何处理这种情况?

英文:

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

type ProductType string

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

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

In Create function I have type form param:

type := req.Form.Get(&quot;type&quot;)

<br>
Question: how to check is type valid?
<br>
<br>
Simplest way is:

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

but what I supposed to do if Product will have 100 types?
<br>
<br>
How to do this in go way?

答案1

得分: 4

使用类型别名引用基本类型的方式,为什么不使用类型别名引用私有类型(即在包外部无法初始化的结构体)呢?

参考这个示例

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") // 无法将类型为string的"test"用作printProductType的参数类型ProductType
    printProductType(PtRouteTransportation)
}

这意味着你只能使用在var部分定义的公共值。

如果你成功将一个值传递给printProductType(pt ProductType),那么你的值总是有效的。


对于动态检查部分,OneOfOne他的答案中提到,我会添加一个函数GetProductType(name string) ProductType,该函数:

  • 检查名称是否有效
  • 返回在上面的var部分定义的官方ProductType实例之一。

这样,你的代码的其余部分始终使用官方的ProductType值(而不是与正确值匹配的'string')。

英文:

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{&quot;ProductRT&quot;})
	PtOnDemandTransportation ProductType = ProductType(productType{&quot;ProductDT&quot;})
	PtExcursion              ProductType = ProductType(productType{&quot;ProductEX&quot;})
	PtTicket                 ProductType = ProductType(productType{&quot;ProductTK&quot;})
	PtQuote                  ProductType = ProductType(productType{&quot;ProductQT&quot;})
	PtGood                   ProductType = ProductType(productType{&quot;ProductGD&quot;})
)

func printProductType(pt ProductType) {
	fmt.Println(pt.name)
}
func main() {
	fmt.Println(&quot;Hello, playground&quot;)
	// printProductType(&quot;test&quot;) // cannot use &quot;test&quot; (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)

答案2

得分: 3

最简单的方法是使用一个映射(map),虽然不如常量快,但如果你需要对一个大集合进行测试,这是最方便的方式。

另外,由于它是预分配的,所以它是线程安全的,所以你不需要担心锁的问题,除非你在运行时添加元素。

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

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

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{}{
		&quot;ProductRT&quot;: {},
		&quot;ProductDT&quot;: {},
		&quot;ProductEX&quot;: {},
		&quot;ProductTK&quot;: {},
		&quot;ProductQT&quot;: {},
		&quot;ProductGD&quot;: {},
	}

)

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

huangapple
  • 本文由 发表于 2014年12月2日 21:00:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/27250086.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定