【问题标题】:Data structure that only allows one of a set? Golang [duplicate]只允许一组中的一个的数据结构? Golang [重复]
【发布时间】:2016-12-22 06:18:22
【问题描述】:

什么是只允许一组可能选项中的一个的数据结构?

我尝试过使用enums,但它们不是我想要的。

package main

import "fmt"

type Event struct {
        day_number Day 
}

type Day int 

const (
        Monday Day = iota
        Tuesday
        Wednesday
        Thursday
        Friday
        Saturday
        Sunday
)

func main() {
        var r Event
        r.day_number = Monday
        fmt.Println(r.day_number)
        // Keep this from happening.
        var impossible Event
        impossible.day_number = 12
        fmt.Println(impossible.day_number)
}

【问题讨论】:

    标签: go enums


    【解决方案1】:

    您可以使用不同的包隐藏成员字段。这将创建结构的方式限制为该包中的函数,然后您可以控制这些函数以接受一组有限的输入。

    foo/foo.go:

    package foo
    
    import "fmt"
    
    type entity int
    
    const (
        one entity = iota + 1
        two
    )
    
    type Foo struct {
        e entity
    }
    
    func (f Foo) Get() int {
        return int(f.e)
    }
    
    func NewFoo(i int) Foo {
        switch i {
        case 1:
            return Foo{one}
        case 2:
            return Foo{two}
        default:
            panic(fmt.Errorf("%s", "foo"))
        }
    }
    

    bar.go:

    package main
    
    import "fmt"
    import "./foo"
    
    func main() {
        f := foo.NewFoo(2)
        fmt.Println(f.Get())
        e := foo.Foo{3}  // Error: implicit assignment of unexported field 'e' in foo.Foo literal
        fmt.Println(e.Get())
        d := foo.NewFoo(3) // panic: foo!
        fmt.Println(d.Get())
    }
    

    您不能在foo 包之外创建Foo 结构,并且在foo 包中创建Foo 结构的唯一函数只接受一组有限的值。

    【讨论】:

      【解决方案2】:

      我不确定这是否有意义,因为您的 day_number 字段在您的包之外已经无法访问。

      不过,如果确实有必要,您可以通过验证输入的方法设置私有字段,例如下面的 SetDay 方法:

      func (d Day) String() string {
          if v, ok := map[Day]string{
              Monday:    "Monday",
              Tuesday:   "Tuesday",
              Wednesday: "Wednesday",
              Thursday:  "Thursday",
              Friday:    "Friday",
              Saturday:  "Saturday",
              Sunday:    "Sunday",
          }[d]; ok {
              return v
          }
          return "Bad day"
      }
      
      func (e *Event) SetDay(d Day) error {
          if v := d.String(); v == "Bad day" {
              return fmt.Errorf(v)
          }
          e.day_number = d
          return nil
      }
      

      Playground link

      【讨论】:

        猜你喜欢
        • 2019-05-12
        • 1970-01-01
        • 2013-08-08
        • 1970-01-01
        • 1970-01-01
        • 2017-06-05
        • 2021-11-26
        • 2021-08-22
        • 2022-12-07
        相关资源
        最近更新 更多