How to check if an attribute exists in an object's dynamic struct

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

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)
    }
}

https://play.golang.org/p/KIjfC7Rdyls

答案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{})
}

huangapple
  • 本文由 发表于 2021年8月16日 14:05:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/68798048.html
匿名

发表评论

匿名网友

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

确定