Golang中如何将对象添加到[]interface{}并调用其Display()方法

Golang中如何将对象添加到[]interface{}并调用其Display()方法 我已完成以下操作:

  • 定义了一个包含 Display() 方法的"父"接口
  • 创建了 2 个子结构体,分别实现了各自的 Display() 方法
  • 在 main() 中创建了 2 个子对象并将它们添加到:availableObjs[]interface{}
  • 现在,在 For 循环中,想要获取对象并调用其相应的 Display() 函数。这就是我卡住的地方

GoPlayground 代码: https://play.golang.org/p/jdHpueokrEk

相同代码内联:

package main

import (
	"fmt"
	"reflect"
)

////// 包含 Display() 方法的父接口
type Parent interface {
	Display()
}

// 2 个子结构体实现各自的 Display() 方法
type Child1 struct {
	name1 string
}

type Child2 struct {
	name2 string
}

func (c1 Child1) Display() {
	fmt.Println("c1Name : ", c1.name1)
}

func (c2 Child2) Display() {
	fmt.Println("c2Name : ", c2.name2)
}
////////////////////////////////////////////

// 维护已创建的对象
var availableObjs []interface{}

func main() {
	//// 创建 2 个对象
	c1 := Child1{"Child1"}
	c2 := Child2{"Child2"}

	// 将 2 个对象添加到 availableObjs
	availableObjs = append(availableObjs, c1)
	availableObjs = append(availableObjs, c2)

	// 现在,想要从接口中获取对象并调用其相应的 Display() 方法
	for _, obj := range availableObjs {
	        fmt.Println("")
		fmt.Println("Obj Got = ",obj)
		fmt.Println("Obj type = ",reflect.TypeOf(obj))
		//obj.Display()        //  <-- 问题行
	}
}

更多关于Golang中如何将对象添加到[]interface{}并调用其Display()方法的实战教程也可以访问 https://www.itying.com/category-94-b0.html

3 回复

两种方法对我都有效。我会选择方案2。感谢您的帮助!

更多关于Golang中如何将对象添加到[]interface{}并调用其Display()方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


为什么你要使用 interface{} 切片而不是 Parent 类型的切片?你当然可以通过类型断言来调用 Display 方法,如下所示:

for _, obj := range availableObjs {
		p := obj.(Parent)
		p.Display()
}

但更直接的方式是直接使用 Parent 类型的切片:

r availableObjs []Parent

func main() {
	//// Creating 2 objects
	c1 := Child1{"Child1"}
	c2 := Child2{"Child2"}

	// Adding 2 objects to availableObjs
	availableObjs = append(availableObjs, c1)
	availableObjs = append(availableObjs, c2)

	// Now, want to fetch the Object from Interface and call its respective Display() fn.
	for _, obj := range availableObjs {
		obj.Display()
	}
}

要解决这个问题,你需要将 interface{} 类型断言为 Parent 接口类型,然后调用 Display() 方法。以下是修改后的代码:

package main

import (
	"fmt"
)

type Parent interface {
	Display()
}

type Child1 struct {
	name1 string
}

type Child2 struct {
	name2 string
}

func (c1 Child1) Display() {
	fmt.Println("c1Name : ", c1.name1)
}

func (c2 Child2) Display() {
	fmt.Println("c2Name : ", c2.name2)
}

var availableObjs []interface{}

func main() {
	c1 := Child1{"Child1"}
	c2 := Child2{"Child2"}

	availableObjs = append(availableObjs, c1)
	availableObjs = append(availableObjs, c2)

	for _, obj := range availableObjs {
		fmt.Println("")
		fmt.Println("Obj Got = ", obj)
		
		// 类型断言为 Parent 接口
		if parent, ok := obj.(Parent); ok {
			parent.Display()
		} else {
			fmt.Println("对象未实现 Parent 接口")
		}
	}
}

运行结果:

Obj Got =  {Child1}
c1Name :  Child1

Obj Got =  {Child2}
c2Name :  Child2

关键修改是在循环中使用类型断言 obj.(Parent),这会检查 interface{} 是否实现了 Parent 接口。如果断言成功,就可以调用 Display() 方法。

另一种更简洁的写法是直接使用 Parent 类型的切片:

var availableObjs []Parent

func main() {
	c1 := Child1{"Child1"}
	c2 := Child2{"Child2"}

	availableObjs = append(availableObjs, c1)
	availableObjs = append(availableObjs, c2)

	for _, obj := range availableObjs {
		fmt.Println("")
		fmt.Println("Obj Got = ", obj)
		obj.Display()  // 直接调用,无需类型断言
	}
}

这样就不需要在循环中进行类型断言,代码更加简洁。

回到顶部