英文:
How to use a string enum with a method as a generic parameter?
问题
我有多个基于字符串的枚举类型,它们共享一个名为Validate()
的公共方法(都在我控制之外)。我想要一个通用的方法,将字符串转换为这些枚举类型,并在结果枚举上调用Validate()
方法。我尝试使用泛型来实现这一点,但由于各种原因失败了。
在下面的示例中,类型约束太强,阻止了对Validate()
的调用。我还尝试过插入自己的带有Validate()
方法的接口,并将其用作类型约束,但在类型转换部分失败了。
如何在不修改枚举类型的情况下实现这一点?
package main
// 假设我无法控制的情况下有多个这样的类型
type FooStatusEnum string
func NewFooStatusEnum(value FooStatusEnum) *FooStatusEnum {
return &value
}
const (
FooStatusEnumA FooStatusEnum = "A"
FooStatusEnumB FooStatusEnum = "B"
FooStatusEnumC FooStatusEnum = "C"
)
func (m FooStatusEnum) Validate() error {
return nil
}
func stringToValidatedEnum[E ~string](s string) E {
e := E(s)
if err := e.Validate(); err != nil {
panic(1)
}
return e
}
func main() {
stringToValidatedEnum[FooStatusEnum]("A")
e := FooStatusEnum("A")
e.Validate()
}
英文:
I have multiple string-derived enums that share a common Validate()
method (all outside of my control). I would like a generic method that converts a string to those enums and calls Validate()
on the resulting enum. I've tried to achieve this with generics but failed for various reasons.
In the example below the type constrained is too strong and prevents a call to Validate()
. I've also tried inserting my own interface with a Validate()
method and use it as a type constrained, but then failed on the type conversion part.
How can I achieve this without modifying the enums?
package main
// imagine i have multiple of those types outside of my control
type FooStatusEnum string
func NewFooStatusEnum(value FooStatusEnum) *FooStatusEnum {
return &value
}
const (
FooStatusEnumA FooStatusEnum = "A"
FooStatusEnumB FooStatusEnum = "B"
FooStatusEnumC FooStatusEnum = "C"
)
func (m FooStatusEnum) Validate() error {
return nil
}
func stringToValidatedEnum[E ~string](s string) E {
e := E(s)
if err := e.Validate(); err != nil {
panic(1)
}
return e
}
func main() {
stringToValidatedEnum[FooStatusEnum]("A")
e := FooStatusEnum("A")
e.Validate()
}
答案1
得分: 4
使用类型约束来同时指定string
底层类型和Validate()
方法:
type enumString interface {
~string
Validate() error
}
func stringToValidatedEnum[E enumString](s string) E {
e := E(s)
if err := e.Validate(); err != nil {
panic(1)
}
return e
}
// 测试:
result := stringToValidatedEnum[FooStatusEnum]("A")
fmt.Printf("%T %v", result, result)
这将输出(在Go Playground上尝试):
main.FooStatusEnum A
英文:
Use a type constraint that both specifies string
underlying type and the Validate()
method:
type enumString interface {
~string
Validate() error
}
func stringToValidatedEnum[E enumString](s string) E {
e := E(s)
if err := e.Validate(); err != nil {
panic(1)
}
return e
}
Testing it:
result := stringToValidatedEnum[FooStatusEnum]("A")
fmt.Printf("%T %v", result, result)
This will output (try it on the Go Playground):
main.FooStatusEnum A
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论