【问题标题】:How to make a struct field be a value from list?如何使结构字段成为列表中的值?
【发布时间】:2017-02-24 17:11:13
【问题描述】:

我有一个访问权限列表:

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

还有一个表示路由的结构体:

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

如何将Route 结构的AccessLevel 字段值限制为上面的那些常量之一?

【问题讨论】:

标签: go


【解决方案1】:

施加此类限制的唯一方法是不导出字段,并在任何 setter 方法中进行检查。

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
}

【讨论】:

  • @Danilio 隐私的粒度是golang中的包。在 OOP 语言中可能是同一个类的函数可以访问这里的私有成员,范围是包
  • accessLevel 字段仍然可以由同一包中的任何代码直接设置。我们的两个答案都未能回答操作“我如何限制 [...] 字段值 [...] 只是上面的那些 const 之一?”的问题。真正的答案是:你不能。任何能够接受 const 类型的字段都可以接受其他值。
【解决方案2】:

你不能。 Go 不支持枚举。但是,您可以靠近它。只需为您的访问级别引入一个单独的类型:

type AccessLevel uint64

并使 const 成为以下类型:

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

然后将字段定义为该类型:

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

现在您可以分配这些常量,但不能分配“正常”uint64

需要注意的是,您仍然可以通过AccessLevel(1234)uint64 转换为AccessLevel

【讨论】:

  • 我不认为这会施加 OP 所说的限制。它使常量成为 AccessLevel 类型,其中 AccessLevel 类型是一个更大的域。
  • @hashcode55 我知道,但是 OP 想要的限制在 go 中是不可能的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-12-20
  • 1970-01-01
  • 2018-05-03
  • 2021-12-20
  • 2021-07-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多