遍历混合类型的切片

huangapple go评论75阅读模式
英文:

Iterate over mixed type slice

问题

你可以使用类型断言来访问每种结构体的字段。类型断言允许你将接口类型转换为具体的结构体类型,并访问其字段。

在你的代码中,你可以使用类型断言来访问每个结构体的字段。以下是修改后的代码示例:

package main

import "fmt"

type X struct {
	Type string
	Num  int
}

type Y struct {
	Type string
	Num  int
}

type Z struct {
	Type string
	Num  int
}

func main() {
	var items []interface{}
	x := X{Type: "X-type", Num: 1}
	items = append(items, x)

	y := Y{Type: "Y-type", Num: 2}
	items = append(items, y)

	z := Z{Type: "Z-type", Num: 3}
	items = append(items, z)

	for _, item := range items {
		fmt.Println(item) //{X-type 1} {Y-type 2} {Z-type 3}

		switch item := item.(type) {
		case X:
			fmt.Println(item.Num)  // Access X struct field
			fmt.Println(item.Type) // Access X struct field
		case Y:
			fmt.Println(item.Num)  // Access Y struct field
			fmt.Println(item.Type) // Access Y struct field
		case Z:
			fmt.Println(item.Num)  // Access Z struct field
			fmt.Println(item.Type) // Access Z struct field
		}
	}
}

通过使用类型断言,你可以根据具体的结构体类型访问每个结构体的字段。在上面的示例中,我们使用了switch语句来检查每个item的类型,并根据类型访问相应的字段。

英文:

I need to have different types of structs in a slice. But I can't access the field values of each struct.

package main

import "fmt"

type X struct {
	Type string
	Num  int
}

type Y struct {
	Type string
	Num  int
}

type Z struct {
	Type string
	Num  int
}

func main() {
	var items []interface{}
	x := X{Type: "X-type", Num: 1}
	items = append(items, x)

	y := Y{Type: "Y-type", Num: 2}
	items = append(items, y)

	z := Z{Type: "Z-type", Num: 3}
	items = append(items, z)

	for _, item := range items {
		fmt.Println(item) //{X-type 1} {Y-type 2} {Z-type 3}
		//fmt.Println(item.Num) // item.Num undefined (type interface{} has no field or method Num)
		//fmt.Println(item.Type) // item.Type undefined (type interface{} has no field or method Type)
	}
}

How can I access the individual fields for each type of struct?

答案1

得分: 1

有几种选择。

使用类型开关(type switch):

for _, item := range items {
    switch item := item.(type) {
    case X:
        fmt.Printf("X: %d\n", item.Num)
    case Y:
        fmt.Printf("Y: %d\n", item.Num)
    case Z:
        fmt.Printf("Z: %d\n", item.Num)
    default:
        // 添加处理不支持类型的代码
    }
}

使用反射包按名称访问字段:

for _, item := range items {
    fmt.Println(reflect.ValueOf(item).FieldByName("Num").Interface().(int))
}

使用接口:

为每种类型添加一个访问器方法:

func (x X) GetNum() int { return x.Num }
func (y Y) GetNum() int { return y.Num }
func (z Z) GetNum() int { return z.Num }

声明一个接口:

type GetNumer interface {
    GetNum() int
}

使用接口:

var items []GetNumer
x := X{Type: "X-type", Num: 1}
items = append(items, x)
...
for _, item := range items {
    fmt.Println(item) //{X-type 1} {Y-type 2} {Z-type 3}
    fmt.Println(item.GetNum())
}
英文:

There are a couple of options.

Use a type switch:

for _, item := range items {
	switch item := item.(type) {
	case X:
		fmt.Printf("X: %d\n", item.Num)
	case Y:
		fmt.Printf("Y: %d\n", item.Num)
	case Z:
		fmt.Printf("Z: %d\n", item.Num)
	default:
        // add code to handle unsupported type
	}
}

Use the reflect package to access the fields by name:

for _, item := range items {
	fmt.Println(reflect.ValueOf(item).FieldByName("Num").Interface().(int))
}

Use interfaces:

Add an accessor method to each type:

func (x X) GetNum() int { return x.Num }
func (y Y) GetNum() int { return y.Num }
func (z Z) GetNum() int { return z.Num }

Declare an interface:

type GetNumer interface {
	GetNum() int
}

Use the interface:

var items []GetNumer
x := X{Type: "X-type", Num: 1}
items = append(items, x)
...
for _, item := range items {
	fmt.Println(item) //{X-type 1} {Y-type 2} {Z-type 3}
	fmt.Println(item.GetNum())
}

huangapple
  • 本文由 发表于 2023年3月2日 03:52:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/75608324.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定