如何通过接口设置结构字段?

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

How to set struct fields throw interface?

问题

大家好!

我的任务是解析命令行参数并填充结构体字段。我的函数必须能处理各种类型的参数-它们将在结构体标签中描述。

例如:

type CommndLineArguments struct {
   Configfile string `required:"false" name:"config" default:"/etc/daemon.conf" description:"配置文件"`
   Daemon     bool `required:"true" name:"daemon" default:"false" description:"作为守护进程运行"`
}

我使用reflectflag包。像这样:

func GetArguments(variable interface{}) error {
//检查是否为指向结构体的指针
variableType := reflect.TypeOf(variable)
if variableType.Kind() != reflect.Ptr {
	return errors.New(ERR_PASS_BY_VALUE)
} else if variableValue := variableType.Elem(); variableValue.Kind() != reflect.Struct {
	return errors.New(ERR_NOT_A_STRUCT)
}

// 解析参数

variableValue := variableType.Elem()

for i := 0; i < variableValue.NumField(); i++ {
	structField := variableValue.Field(i)
	fieldName := structField.Name
	fieldType := structField.Type
	fieldTag := structField.Tag

现在我准备解析参数了。

switch fieldType.Kind() {
	case reflect.Bool:
		defaultValue, err := strconv.ParseBool(fieldTag.Get("default"))
		if err != nil {
			return errors.New(ERR_PARSE_ERROR + err.Error())
		}
		flag.BoolVar(&structField, fieldName, defaultValue, fieldTag.Get("description"))

但是我在最后一行遇到了一个错误。

./parser.go:42: cannot use &structField (type *reflect.StructField) as type *bool in function argument

我的问题是如何正确设置这个字段?

英文:

everyone!

My task is to parse command-line argument and fill struct fields. And my function must works with all kinds of arguments - they'll describe in struct tag.

For example:

type CommndLineArguments struct {
   Configfile string `required:&quot;false&quot; name:&quot;config&quot; default:&quot;/etc/daemon.conf&quot; description:&quot;Config file&quot;`
   Daemon     bool `required:&quot;true&quot; name:&quot;daemon&quot; default:&quot;false&quot; description:&quot;Run as daemon&quot;`
}

I use reflect and flag packages. Like this:

func 	GetArguments(variable interface{}) error {
//Check is this a pointer to struct
variableType := reflect.TypeOf(variable)
if variableType.Kind() != reflect.Ptr {
	return errors.New(ERR_PASS_BY_VALUE)
} else if variableValue := variableType.Elem(); variableValue.Kind() != reflect.Struct {
	return errors.New(ERR_NOT_A_STRUCT)
}

// Parse parameters

variableValue := variableType.Elem()

for i := 0; i &lt; variableValue.NumField(); i++ {
	structField := variableValue.Field(i)
	fieldName := structField.Name
	fieldType := structField.Type
	fieldTag := structField.Tag

Now I'm ready to parse arguments.

switch fieldType.Kind() {
	case reflect.Bool:
		defaultValue, err := strconv.ParseBool(fieldTag.Get(&quot;default&quot;))
		if err != nil {
			return errors.New(ERR_PARSE_ERROR + err.Error())
		}
		flag.BoolVar(&amp;structField, fieldName, defaultValue, fieldTag.Get(&quot;description&quot;))

But I get an error in last line.

./parser.go:42: cannot use &amp;structField (type *reflect.StructField) as type *bool in function argument

My question is how can I set this field correctly?

答案1

得分: 0

你需要获取字段的地址(也使用ValueOf而不是TypeOf):

flag.BoolVar(fld.Addr().Interface().(*bool), fieldName, defaultValue, fieldTag.Get("description"))

简单示例 @ http://play.golang.org/p/yEG-OH6d4W

英文:

You will have to get the address of the field (also use ValueOf not TypeOf):

flag.BoolVar(fld.Addr().Interface().(*bool), fieldName, defaultValue, fieldTag.Get(&quot;description&quot;))

Simple demo @ http://play.golang.org/p/yEG-OH6d4W

huangapple
  • 本文由 发表于 2014年7月10日 19:33:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/24675469.html
匿名

发表评论

匿名网友

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

确定