英文:
Data structure that only allows one of a set? Golang
问题
只允许一组可能选项的数据结构是什么?
我尝试使用enum进行操作,但它们不是我想要的。
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)
    // 防止这种情况发生。
    var impossible Event
    impossible.day_number = 12
    fmt.Println(impossible.day_number)
}
英文:
What's a data structure that only allows one of a possible set of options?
I tried playing around with enums but they are not what I want.
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)
}
答案1
得分: 2
你可以使用不同的包来隐藏成员字段。这将限制只能使用该包中的函数来创建该结构,并且你可以控制这些函数只接受有限的输入集合。
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}  // 错误:在 foo.Foo 字面值中隐式分配了未导出的字段 'e'
    fmt.Println(e.Get())
    d := foo.NewFoo(3) // panic: foo!
    fmt.Println(d.Get())
}
在 foo 包之外无法创建 Foo 结构体,而在 foo 包中,只有一个函数可以创建 Foo 结构体,并且只接受有限的值。
英文:
You could hide away the member field using a different package. This limits ways of creating the structure to functions from that package, and you can then control those functions to accept a limited set of inputs.
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())
}
You cannot create a Foo struct outside of the foo package, and the only function that creates Foo structs in a foo package accepts only a limited set of values.
答案2
得分: 0
我不确定这是否有太多意义,因为你的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
}
英文:
I'm not sure this makes much sense since your day_number field is already inaccessible outside your package.
Still, if this is really necessary, you'd set the private field via a method that validates the input such as the SetDay method below:
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
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论