如何使用反射在Go语言中设置一个指向字符串的结构成员呢?

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

How to set a struct member that is a pointer to a string using reflection in Go

问题

我正在尝试使用反射来设置一个指针。elasticbeanstalk.CreateEnvironmentInput有一个名为SolutionStackName的字段,类型为*string。当我尝试设置任何值时,我得到以下错误:

panic: reflect: call of reflect.Value.SetPointer on ptr Value

以下是我的代码:

...
newEnvCnf := new(elasticbeanstalk.CreateEnvironmentInput)
checkConfig2(newEnvCnf, "SolutionStackName", "teststring")
...
func checkConfig2(cnf interface{}, key string, value string) bool {
    log.Infof("key %v, value %s", key, value)
   
    v := reflect.ValueOf(cnf).Elem()
    fld := v.FieldByName(key)

    if fld.IsValid() {
        if fld.IsNil() && fld.CanSet() {
            fld.SetPointer(unsafe.Pointer(aws.String(value)))
            //aws.String返回一个指针
        }
    }
...

以下是日志输出:

time="2016-02-20T23:54:52-08:00" level=info msg="key [SolutionStackName], value teststring" 
panic: reflect: call of reflect.Value.SetPointer on ptr Value [recovered]
    panic: reflect: call of reflect.Value.SetPointer on ptr Value
英文:

I am trying to use reflection to set a pointer. elasticbeanstalk.CreateEnvironmentInput has a field SolutionStackName which is of type *string. I am getting the following error when I try to set any value:

panic: reflect: call of reflect.Value.SetPointer on ptr Value

Here is my code:

    ...
newEnvCnf := new(elasticbeanstalk.CreateEnvironmentInput)
checkConfig2(newEnvCnf, "SolutionStackName", "teststring")
    ...
func checkConfig2(cnf interface{}, key string, value string) bool {
	log.Infof("key %v, value %s", key, value)
   
	v := reflect.ValueOf(cnf).Elem()
	fld := v.FieldByName(key)

	if fld.IsValid() {
		if fld.IsNil() && fld.CanSet() {
			fld.SetPointer(unsafe.Pointer(aws.String(value)))
//aws.String returns a pointer
		
...

Here is the log output

time="2016-02-20T23:54:52-08:00" level=info msg="key [SolutionStackName], value teststring" 
	panic: reflect: call of reflect.Value.SetPointer on ptr Value [recovered]
		panic: reflect: call of reflect.Value.SetPointer on ptr Value

答案1

得分: 8

Value.SetPointer() 只能在值的类型为 reflect.UnsafePointer 时使用(通过 Value.Kind() 报告),但你的类型是 reflect.Ptr,所以 SetPointer() 会引发 panic(如文档所述)。

只需使用 Value.Set() 方法来更改结构字段的值(无论它是指针还是非指针都无关紧要)。它期望一个类型为 reflect.Value 的参数,你可以通过调用 reflect.ValueOf() 来获取它,并简单地传递参数 value 的地址:

fld.Set(reflect.ValueOf(&value))

进行测试:

type Config struct {
    SolutionStackName *string
}

c := new(Config)
fmt.Println(c.SolutionStackName)
checkConfig2(c, "SolutionStackName", "teststring")
fmt.Println(*c.SolutionStackName)

输出结果(在 Go Playground 上尝试):

<nil>
teststring
英文:

Value.SetPointer() can only be used if the value's kind is reflect.UnsafePointer (as reported by Value.Kind()), but yours is reflect.Ptr so SetPointer() will panic (as documented).

Simply use the Value.Set() method to change the value of the struct field (it being pointer or not, doesn't matter). It expects an argument of type reflect.Value which you can obtain by calling reflect.ValueOf(), and simply pass the address of the parameter value:

fld.Set(reflect.ValueOf(&amp;value))

Testing it:

type Config struct {
	SolutionStackName *string
}

c := new(Config)
fmt.Println(c.SolutionStackName)
checkConfig2(c, &quot;SolutionStackName&quot;, &quot;teststring&quot;)
fmt.Println(*c.SolutionStackName)

Output (try it on the Go Playground):

&lt;nil&gt;
teststring

huangapple
  • 本文由 发表于 2016年2月21日 16:15:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/35533837.html
匿名

发表评论

匿名网友

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

确定