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

问题描述 投票:8回答:7

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

type StatusType int

const (
    PENDING StatusType = iota
    APPROVED
    REJECTED
)

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

go enums
7个回答
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实现了StatusTyper接口.Caveat applies。)


8
投票

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

package StatusType

type Int int

const (
    Pending Int = iota
    Approved
    Rejected
    end
)

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

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

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
}

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

Test(StatusType.Approved)

3
投票

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


0
投票

使用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
}

0
投票

iota只是一个编译器。代码相当于:

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

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

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

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())
}

-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
)
© www.soinside.com 2019 - 2024. All rights reserved.