如何在golang中检查值是否为iota常量?

时间:2016-05-28 06:48:28

标签: go enums

我在golang中使用iota定义了以下类型。

type StatusType int

const (
    PENDING StatusType = iota
    APPROVED
    REJECTED
)

我想将REST-API中传递的值限制为StatusType。这样的值不应超过0,1,2。

7 个答案:

答案 0 :(得分:8)

只是不要导出StatusType(假设您在包“status”中定义它。) 这遵循“What is an idiomatic way of representing enums in Go?”:

type statusType int

const (
    PENDING statusType = iota
    APPROVED
    REJECTED
)
type StatusTyper interface {
    StatusType() statusType 
}

func(st statusType) StatusType() statusType {
    return st
}

然后,任何外部包都会引用StatusType - 变量为status.PENDINGstatus.APPROVEDstatus.REJECTED
(实现statusType接口的唯一三个StatusTyperCaveat applies。)

答案 1 :(得分:8)

我这样做:
首先创建一个名为“StatusType”的包(在名为StatusType的文件夹中):
filename:$ GOPATH / enum / StatusType / StatusType.go

-1

并像这样使用($ GOPATH / enum / main.go):

package StatusType

type Int int

const (
    Pending Int = iota
    Approved
    Rejected
    end
)

func IsValid(value int) bool {
    return value < int(end)
}

StatusType包只会导出您需要的内容,因此无需检查iota const范围 如果您想检查,请使用:StatusType.IsValid()
关于StatusType包的好处是:
当你想要StatusType类型的函数参数时,使用StatusType.Int,它显示它是int类型的枚举 像:

package main

import (
    "enum/StatusType"
    "fmt"
)

func Test(enum StatusType.Int) {
    fmt.Println(enum) //1
}
func main() {
    Test(StatusType.Approved)

    fmt.Println(StatusType.IsValid(1))  //true
    fmt.Println(StatusType.IsValid(10)) //false
}

答案 2 :(得分:3)

假设您希望无效的JSON有效负载失败,请实施Unmarshaler接口:https://play.golang.org/p/zuchzQ0vmo

答案 3 :(得分:0)

使用go github.com/alvaroloes/enumer生成

package main

import "fmt"

//go:generate enumer -type=StatusType
type StatusType int

const (
    PENDING StatusType = iota
    APPROVED
    REJECTED
)

func main() {
    fmt.Println(StatusType(0).IsAStatusType()) // true
    fmt.Println(StatusType(1).IsAStatusType()) // true
    fmt.Println(StatusType(2).IsAStatusType()) // true
    fmt.Println(StatusType(3).IsAStatusType()) // false
}

答案 4 :(得分:0)

iota仅仅是一个编译器。该代码等效于:

const PENDING int = 0
const APPROVED int = 1
...

因此,要设计一个函数CheckValid()来确定该值是否在给定值中。 如果您的const处于连续范围内,则可以使用user6169399的方法。 或者,您可以简单地定义一个变量映射[YOUR_TYPE_HERE] bool进行验证。

func (t YOUR_TYPE) CheckValid(){
    if _, ok:=map[t];ok return true
    else return false
}

答案 5 :(得分:0)

这里有另外两种无需地图即可完成此操作的方法 https://play.golang.org/p/eKW_KPshx7b

package main

import (
    "errors"
    "log"
)

type StatusType int

const (
    PENDING StatusType = iota
    APPROVED
    REJECTED
)

func Validate(val int) (bool, error) {
    if v := StatusType(val); v > REJECTED || v < PENDING {
        return false, errors.New("invalid StatusType")
    }
    return true, nil
}

func (t StatusType) Validate() (bool, error) {
    if t > REJECTED || t < PENDING {
        return false, errors.New("invalid StatusType")
    }
    return true, nil
}


func main() {
    log.Print(Validate(-1))
    log.Print(Validate(0))
    log.Print(Validate(1))
    log.Print(Validate(3))

    log.Print(StatusType(-1).Validate())
    log.Print(StatusType(1).Validate())
    log.Print(StatusType(10).Validate())
}

答案 6 :(得分:-1)

我也很努力地解决这个问题,因为我真的想找到一种简单的方法来检查传入的值是否在正确的范围内。我想到的技巧如下:

type StatusType int

const (
    PENDING StatusType = iota
    APPROVED
    REJECTED
)

func (st StatusType) String() string {
    switch st {
    case PENDING:
        return "STATUS:PENDING"
    case APPROVED:
        return "STATUS:APPROVED"
    case REJECTED:
        return "STATUS:REJECTED"
    defaut:
        return "INVALID"
    }
}

func (st StatusType) IsValid() bool {
    return st.String() != "INVALID"
}

由于我经常需要将枚举值转换为有意义的表示形式,因此我倾向于向枚举类型添加String()。这些案例涵盖了所有合法值,而默认路径捕获了该值无效的情况。

简单地说,要检查某个值是否有效,请将其字符串表示形式与默认情况进行比较。

我的解决方案的一个好处是,如果将来添加另一个枚举值,则只需在String()方法中添加一个大小写。 IsValid()方法仍然有效。

另一个好处是,在值的范围不连续的情况下,我的解决方案也适用。如以下定义:

const (
    PENDING  StatusType = 1001
    APPROVED            = 1003
    REJECTED            = 1005
)