Go - 在列表中存储具有相同嵌入结构的结构
Go - storing structs with the same embedded struct in a list
我有多个具有相同嵌入式结构的结构。在其中一个结构中,我想存储嵌入基本结构的任何结构的列表。这是一个显示案例的小片段。
package main
type Symbol interface{}
type Base struct {
a int32
}
type Foo struct {
Base
b int32
Symbols []Base
// Below works
// Symbols []Symbol
}
type Bar struct {
Base
c int32
}
func main () {
var bar Bar
var foo Foo
foo.Symbols = append(foo.Symbols, bar)
}
但是,这不起作用。我得到 ./main.go:25:22: cannot use bar (type Bar) as type Base in append
。当我使用空 Symbol
界面时,一切正常。然而,这种方法完全绕过了类型系统,因为现在所有内容都可以存储在列表中。我想以某种方式表示列表中只能存储 Base
、Foo
和 Bar
,以便编译器可以检查是否满足此要求。我的结构没有任何方法,当然没有共享行为并可以添加到接口的方法。向接口和虚拟实现添加一些虚拟方法似乎非常人为。处理此类场景的 Go 惯用方式是什么?
重要的是相同的界面:
package main
import (
"fmt"
)
type Item interface{
fmt.Stringer
}
type ItemA struct {
}
func (a ItemA) String() string {
return "item A"
}
type ItemB struct {
}
func (a ItemB) String() string {
return "item B"
}
func main() {
items := make([]Item, 0)
items = append(items, ItemA{}, ItemB{})
fmt.Printf("Items: %v", items)
}
您似乎期待的是 subtype polymorphism
。 Go 不支持非接口类型的动态绑定。因此你可以使用 interfaces
package main
func main(){
var bar Bar
var foo Foo
foo.Symbols = append(foo.Symbols, bar)
}
type Symbol interface {
Symbol()
}
type Base struct {
a int32
}
func (b Base)Symbol(){}
type Foo struct {
Base
b int32
Symbols []Symbol
}
type Bar struct {
Base
c int32
}
或者如果你不喜欢使用接口,你可以使用像下面这样的技巧来反射。
package main
import "fmt"
func main(){
var bar Bar
var foo Foo
err := foo.AddSymbol(bar)
if err != nil{
fmt.Println(err)
}
}
type Base struct {
a int32
}
func (b Base)Symbol(){}
type Foo struct {
Base
b int32
symbol []interface{} // field made private
}
// AddSymbol : helper to append values
func (f *Foo)AddSymbol(in interface{})(err error){
if f.symbol == nil{
f.symbol = make([]interface{},0)
}
switch typ := in.(type) {
case Base,Bar,Foo:
f.symbol = append(f.symbol,in)
default:
return fmt.Errorf("provided type: %s is not supported",typ)
}
return nil
}
type Bar struct {
Base
c int32
}
我做了一些搜索和阅读。我想要实现的目标需要所谓的“总和类型”。目前 Go 不支持求和类型。但是,几乎没有其他方法可以模拟求和类型的行为。此处对它们进行了很好的描述 Alternatives to sum types in Go.
此外,看起来 Go 2 可能会支持求和类型。进一步阅读 proposal: spec: add sum types / discriminated unions, spec: generics: use type sets to remove type keyword in constraints。
我有多个具有相同嵌入式结构的结构。在其中一个结构中,我想存储嵌入基本结构的任何结构的列表。这是一个显示案例的小片段。
package main
type Symbol interface{}
type Base struct {
a int32
}
type Foo struct {
Base
b int32
Symbols []Base
// Below works
// Symbols []Symbol
}
type Bar struct {
Base
c int32
}
func main () {
var bar Bar
var foo Foo
foo.Symbols = append(foo.Symbols, bar)
}
但是,这不起作用。我得到 ./main.go:25:22: cannot use bar (type Bar) as type Base in append
。当我使用空 Symbol
界面时,一切正常。然而,这种方法完全绕过了类型系统,因为现在所有内容都可以存储在列表中。我想以某种方式表示列表中只能存储 Base
、Foo
和 Bar
,以便编译器可以检查是否满足此要求。我的结构没有任何方法,当然没有共享行为并可以添加到接口的方法。向接口和虚拟实现添加一些虚拟方法似乎非常人为。处理此类场景的 Go 惯用方式是什么?
重要的是相同的界面:
package main
import (
"fmt"
)
type Item interface{
fmt.Stringer
}
type ItemA struct {
}
func (a ItemA) String() string {
return "item A"
}
type ItemB struct {
}
func (a ItemB) String() string {
return "item B"
}
func main() {
items := make([]Item, 0)
items = append(items, ItemA{}, ItemB{})
fmt.Printf("Items: %v", items)
}
您似乎期待的是 subtype polymorphism
。 Go 不支持非接口类型的动态绑定。因此你可以使用 interfaces
package main
func main(){
var bar Bar
var foo Foo
foo.Symbols = append(foo.Symbols, bar)
}
type Symbol interface {
Symbol()
}
type Base struct {
a int32
}
func (b Base)Symbol(){}
type Foo struct {
Base
b int32
Symbols []Symbol
}
type Bar struct {
Base
c int32
}
或者如果你不喜欢使用接口,你可以使用像下面这样的技巧来反射。
package main
import "fmt"
func main(){
var bar Bar
var foo Foo
err := foo.AddSymbol(bar)
if err != nil{
fmt.Println(err)
}
}
type Base struct {
a int32
}
func (b Base)Symbol(){}
type Foo struct {
Base
b int32
symbol []interface{} // field made private
}
// AddSymbol : helper to append values
func (f *Foo)AddSymbol(in interface{})(err error){
if f.symbol == nil{
f.symbol = make([]interface{},0)
}
switch typ := in.(type) {
case Base,Bar,Foo:
f.symbol = append(f.symbol,in)
default:
return fmt.Errorf("provided type: %s is not supported",typ)
}
return nil
}
type Bar struct {
Base
c int32
}
我做了一些搜索和阅读。我想要实现的目标需要所谓的“总和类型”。目前 Go 不支持求和类型。但是,几乎没有其他方法可以模拟求和类型的行为。此处对它们进行了很好的描述 Alternatives to sum types in Go.
此外,看起来 Go 2 可能会支持求和类型。进一步阅读 proposal: spec: add sum types / discriminated unions, spec: generics: use type sets to remove type keyword in constraints。