英文:
How to check if an attribute exists in an object's dynamic struct
问题
我对如何检查对象的动态结构中是否存在属性感到困惑。例如,如果我们有以下结构体:
type Animal struct {
Name string
Origin string
}
type Bird struct {
Animal
Speed float32
CanFly bool
}
type Bear struct {
Animal
Lazy bool
}
现在我有一个使用Animal
作为参数的函数:
func checkAminalSpeed(a Animal){
// 如果当前动物的结构体中没有Speed属性
// 打印"I don't have a speed"
// 否则,返回该动物的速度
}
这个函数试图检查变量的运行时类型以选择操作。
我想知道在这种情况下,如何编写这个checkAminalSpeed
函数?谢谢!
英文:
I'm confused about how to check if an attribute exists in an object's dynamic struct. I.e. if we have the following structs:
type Animal struct {
Name string
Origin string
}
type Bird struct {
Animal
Speed float32
CanFly bool
}
type Bear struct {
Animal
Lazy bool
}
And now I have a function using Animal
as a parameter:
func checkAminalSpeed (a Animal){
// if the struct of current animal doesn't have the Speed attribute
// print ("I don't have a speed")
//otherwise, return the speed of this animal
}
This function is trying to check the varible's runtime type to choose action.
I'd like to know in this case, how to write this checkAminalSpeed
function? Thanks!
答案1
得分: 2
Go语言不支持继承,但也许你会觉得以下方法可行。
使用接口来定义动物的行为:
type Animal interface {
GetName() string
GetOrigin() string
GetSpeed() float32
}
使用一个“基础”类型来包含共同的字段,并实现这些行为:
type AnimalBase struct {
Name string
Origin string
}
func (a AnimalBase) GetName() string { return a.Name }
func (a AnimalBase) GetOrigin() string { return a.Origin }
func (a AnimalBase) GetSpeed() float32 { return -1 }
嵌入“基础”类型并覆盖需要的行为:
type Bird struct {
AnimalBase
Speed float32
CanFly bool
}
func (b Bird) GetSpeed() float32 { return b.Speed }
然后...
func checkAminalSpeed(a Animal) {
if speed := a.GetSpeed(); speed == -1 {
fmt.Println("我没有速度")
} else {
fmt.Println(speed)
}
}
https://play.golang.org/p/KIjfC7Rdyls
英文:
Go does not support inheritance, but perhaps you'll find the following approach tolerable.
Use an interface
to define the Animal
's behaviour:
type Animal interface {
GetName() string
GetOrigin() string
GetSpeed() float32
}
Use a "base" type that will contain common fields and also implement the behaviour:
type AnimalBase struct {
Name string
Origin string
}
func (a AnimalBase) GetName() string { return a.Name }
func (a AnimalBase) GetOrigin() string { return a.Origin }
func (a AnimalBase) GetSpeed() float32 { return -1 }
Embed the "base" type and override any behaviour you need to:
type Bird struct {
AnimalBase
Speed float32
CanFly bool
}
func (b Bird) GetSpeed() float32 { return b.Speed }
And then...
func checkAminalSpeed(a Animal) {
if speed := a.GetSpeed(); speed == -1 {
fmt.Println("I don't have speed")
} else {
fmt.Println(speed)
}
}
答案2
得分: 1
mkopriva是正确的。Go语言不支持继承,但可以使用reflect和interface{}来实现类似的功能。
提示:使用reflect比使用interface{}更耗时。
package main
import (
"fmt"
"reflect"
)
type Animal struct {
Name string
Origin string
}
type Bird struct {
Animal
Speed float32
CanFly bool
}
type Bear struct {
Animal
Lazy bool
}
func checkAnimalSpeed(a interface{}) {
v := reflect.ValueOf(a)
if f, ok := v.Type().FieldByName("Speed"); ok {
fmt.Printf("%v\n", f)
}
}
func main() {
checkAnimalSpeed(Bird{})
checkAnimalSpeed(Bear{})
}
英文:
mkopriva is right. Go does not support inheritance, you can use reflect and interface{} also
ps: reflect cost more time than interface
package main
import (
"fmt"
"reflect"
)
type Animal struct {
Name string
Origin string
}
type Bird struct {
Animal
Speed float32
CanFly bool
}
type Bear struct {
Animal
Lazy bool
}
func checkAminalSpeed (a interface{}){
v := reflect.ValueOf(a)
if f, ok := v.Type().FieldByName("Speed"); ok{
fmt.Printf("%v\n", f)
}
}
func main() {
checkAminalSpeed(Bird{})
checkAminalSpeed(Bear{})
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论