如何检查接口中的导出字段

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

golang: How to check for exported fields in an interface

问题


import (
	"fmt"
	"reflect"
)

type StatusVal int
type Foo struct {
	Name string
	Age  int
	art  string
}

func ListFields(a interface{}) {
	v := reflect.ValueOf(a).Elem()
	fmt.Printf(" Kind: %+v \n", v.Type())
	for _, f := range reflect.VisibleFields(v.Type()) {
		if f.IsExported() {
			fmt.Printf(" Kind: %+v \n", f)
		} else {
			fmt.Printf(" Kind: %s \n", f.Name)
		}
	}

}

func main() {
	var x Foo
	ListFields(&x)

}

这段代码是可以工作的,但我真正需要的是 var x []Foo ,我找不到方法来实现并检查结构体切片中的字段是否为导出字段。

长版本:

我想要生成一个通用的 sqlToStruct 函数,然后我遇到了这个很棒的答案:
https://stackoverflow.com/questions/62240553/generalizing-sql-rows-scan-in-go/62240694#62240694

我没有足够的声望在那里回复。

唯一的问题是,如果我的结构体有任何未导出的字段,它会引发 panic,我希望能够检查并返回一个错误供处理,而不是让它 panic。

另外:我在 Go 中编程的时间非常短,请理解我现在的情况,如果我漏掉了一些非常明显的东西,请原谅。

英文:

short version:


import (
	"fmt"
	"reflect"
)

type StatusVal int
type Foo struct {
	Name string
	Age  int
	art  string
}

func ListFields(a interface{}) {
	v := reflect.ValueOf(a).Elem()
	fmt.Printf(" Kind: %+v \n", v.Type())
	for _, f := range reflect.VisibleFields(v.Type()) {
		if f.IsExported() {
			fmt.Printf(" Kind: %+v \n", f)
		} else {
			fmt.Printf(" Kind: %s \n", f.Name)
		}
	}

}

func main() {
	var x Foo
	ListFields(&x)

}

This code works, but what I really need is var x []Foo , and I cannot find a way to get that to work and check for IsExported in the fields of the slice of structs.

Long version:

I was looking to generate a generic sqlToStruct function, and I bumped into this awesome answer:
https://stackoverflow.com/questions/62240553/generalizing-sql-rows-scan-in-go/62240694#62240694

I don't have the reputation to reply there.

The only problem with that is that if my struct has any unexported fields, it panics, and I would like to check for that and return an error to be handled, rather than let it panic.

Also: I have been coding in go for a very short amount of time, please understand where I am coming from and sorry if I am missing something absolutely obvious.

答案1

得分: 1

func ListFields(a interface{}) {
	rt := reflect.TypeOf(a) // 获取a的类型
	if rt.Kind() == reflect.Ptr {
		rt = rt.Elem() // 使用Elem获取指向的类型
	}
	if rt.Kind() == reflect.Slice {
		rt = rt.Elem() // 使用Elem获取切片元素的类型
	}
	if rt.Kind() == reflect.Ptr { // 处理类似 []*StructType 的输入类型
		rt = rt.Elem() // 使用Elem获取指向的类型
	}
	if rt.Kind() != reflect.Struct {
		return
	}

	fmt.Printf("类型: %+v \n", rt)
	for _, f := range reflect.VisibleFields(rt) {
		if f.IsExported() {
			fmt.Printf("类型: %+v \n", f)
		} else {
			fmt.Printf("类型: %s \n", f.Name)
		}
	}
}

https://go.dev/play/p/0J3VXmFPe87

英文:
func ListFields(a interface{}) {
	rt := reflect.TypeOf(a) // take type of a
	if rt.Kind() == reflect.Ptr {
		rt = rt.Elem() // use Elem to get the pointed-to-type
	}
	if rt.Kind() == reflect.Slice {
		rt = rt.Elem() // use Elem to get type of slice's element
	}
	if rt.Kind() == reflect.Ptr { // handle input of type like []*StructType
		rt = rt.Elem() // use Elem to get the pointed-to-type
	}
	if rt.Kind() != reflect.Struct {
		return
	}

	fmt.Printf(" Kind: %+v \n", rt)
	for _, f := range reflect.VisibleFields(rt) {
		if f.IsExported() {
			fmt.Printf(" Kind: %+v \n", f)
		} else {
			fmt.Printf(" Kind: %s \n", f.Name)
		}
	}
}

https://go.dev/play/p/0J3VXmFPe87

huangapple
  • 本文由 发表于 2022年2月11日 19:21:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/71079285.html
匿名

发表评论

匿名网友

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

确定