英文:
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 enum
s 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
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论