【问题标题】:How to check whether the value is of type iota constant in Golang?如何在Golang中检查值是否为iota常量类型?
【发布时间】:2016-09-26 12:55:08
【问题描述】:

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

type StatusType int

const (
    PENDING StatusType = iota
    APPROVED
    REJECTED
)

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

【问题讨论】:

标签: go enums


【解决方案1】:

我是这样做的:
首先创建一个名为“StatusType”的包(在名为 StatusType 的文件夹内):
文件名:$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)

【讨论】:

  • 我认为-1会被认为是有效的
【解决方案2】:

不要导出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-like 变量称为status.PENDINGstatus.APPROVEDstatus.REJECTED
(仅有的三个statusType 实现了StatusTyper 接口。Caveat applies。)

【讨论】:

  • 使StatusType 未导出并使用接口不会削减它。请参阅我在Golang: Creating a Constant Type and Restricting the Type's Values 中提出的一个肮脏的技巧,即使使用未导出的方法也可以实现接口。事实上,没有任何常量类型可以通过这种方式进行限制。
  • @icza 同意(并赞成)。我考虑过未导出的包装器结构,但我想尽可能接近 OP 的原始代码。正如我在回答中所说,“警告适用”。
【解决方案3】:

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

【讨论】:

    【解决方案4】:

    使用 go generate 和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
    }
    

    【讨论】:

      【解决方案5】:

      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
      }
      

      【讨论】:

        【解决方案6】:

        这里有另外两种方法可以在没有地图的情况下正确地做到这一点 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())
        }
        

        【讨论】:

          猜你喜欢
          • 2016-10-12
          • 2021-11-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-08-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多