0

I have a list of access rights:

const (
    Everyone = 0
    Owner = 1
    Administrator = 2
)

And a struct representing Routes:

type Route struct {
    Name        string
    Method      string
    Pattern     string
    HandlerFunc http.HandlerFunc
    AccessLevel uint64
}

How can I restrict AccessLevel field value of the Route struct be only one of those const from above?

Sergei Basharov
  • 51,276
  • 73
  • 200
  • 335
  • 1
    Related / possible duplicate of [Golang: Creating a Constant Type and Restricting the Type's Values](http://stackoverflow.com/questions/37385007/golang-creating-a-constant-type-and-restricting-the-types-values/37386119#37386119). – icza Feb 24 '17 at 08:53

2 Answers2

1

The only way to impose this type of restriction is by not exporting the field, and doing your checks in any setter method(s).

type Route struct {
    Name        string
    Method      string
    Pattern     string
    HandlerFunc http.HandlerFunc
    accessLevel uint64
}

// AccessLevel getter method
func (r Route) AccessLevel() uint64 {
  return r.accessLevel
}

// SetAccessLevel setter method
func (r Route) SetAccessLevel(value uint64) error {
    if value < 0 || value > 2 {
        return errors.New("AccessLevel must be between 0 and 2, inclusive")
    }
    r.accessLevel = value
    return nil
}
Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
  • 1
    @Danilio The granularity of privacy is the package in golang. In OOP languages may be the functions of same class can access the private members here the scope is package – Sarath Sadasivan Pillai Feb 24 '17 at 08:55
  • The `accessLevel` field can still be set directly by any code in the same package. Both of our answers fail to answer the question of the op "How can I restrict [...] field value [...] be only one of those const from above?" The real answer is: you can't. Any field that is of a type able to take consts, will be able to take other values. – Danilo Feb 24 '17 at 08:56
0

You can't. Go doesn't support enums. However, you can get close to it. Just introduce a separate type for your access level:

type AccessLevel uint64

and make the consts be of the type:

const (
    Everyone      AccessLevel = 0
    Owner                     = 1
    Administrator             = 2
)

Then define the Field to be of that type:

type Route struct {
    // ...
    AccessLevel AccessLevel
}

Now you can assign those consts, but not a "normal" uint64.

The caveat is that you can still type convert a uint64 to a AccessLevel via AccessLevel(1234).

Danilo
  • 3,257
  • 2
  • 19
  • 24
  • I don't think this imposes the restriction which the OP was talking about. Its making the constants to be of AccessLevel type where AccessLevel type is a larger domain. – hashcode55 Feb 24 '17 at 08:27
  • @hashcode55 I know, but the restrictions that OP want's are not possible with go. – Danilo Feb 24 '17 at 08:32