How to check whether the value is of type iota constant in Golang?

15,560

Solution 1

I do this way:
first create a package named "StatusType" (inside a folder named 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)
}

and use like this ($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
}

The StatusType package just exports what you need so there is no need to check against iota const range.
Just in case you want to check, use: StatusType.IsValid()
And nice thing about StatusType package is:
When you want function parameter of StatusType type use StatusType.Int and it reveals that it is enumeration of type int.
Like:

Test(StatusType.Approved)

Solution 2

Simply don't export StatusType (assuming you define it in package 'status').
This follow "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
}

Any external package would then refer to StatusType-like variable as status.PENDING, status.APPROVED or status.REJECTED.
(the only three statusType which implement the StatusTyper interface. Caveat applies.)

Solution 3

Assuming you wish for invalid JSON payloads to fail, implement the Unmarshaler interface: https://play.golang.org/p/zuchzQ0vmo

Solution 4

use go generate with 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
}
Share:
15,560
Shamsher
Author by

Shamsher

Updated on June 12, 2022

Comments

  • Shamsher
    Shamsher about 2 years

    I have the following type defined using iota in Golang.

    type StatusType int
    
    const (
        PENDING StatusType = iota
        APPROVED
        REJECTED
    )
    

    I want to restrict the value passed in REST-API to the StatusType. Such that the value should not exceed 0,1,2.

  • icza
    icza about 8 years
    Making StatusType unexported and using an interface won't cut it. See a dirty trick which I presented in Golang: Creating a Constant Type and Restricting the Type's Values which allows to implement interfaces even with unexported methods. In fact, no constant type can be restricted this way.
  • VonC
    VonC about 8 years
    @icza Agree (and upvoted). I thought about unexported wrapper struct, but I want to stay as close as possible to the original code of the OP. As I say in the answer, "caveat applies".
  • makapuf
    makapuf over 3 years
    I think -1 would be considered valid
  • Avishay28
    Avishay28 about 2 years
    what if someone decide to put another value after REJECTED ?