Golang使用reflect在struct中设置nil字符串指针值

Rya*_*ith 1 reflection null struct pointers go

使用Go的反射包,如果指针为零,有没有办法在结构中设置指针?查看反射包,如果reflect.Value.CanSet()是,false那么任何Set()调用都会产生恐慌.还有另外一种方法,只使用反射包,而不依赖于对结构的任何直接引用?例如,如何在下面的代码中将空的姓氏设置为"Johnson"?

package main

import (
    "fmt"
    "reflect"
)

type Person struct {
    FirstName *string
    LastName  *string
}

func main() {
    p := Person{}
    firstName := "Ryan"
    p.FirstName = &firstName

    rp := reflect.ValueOf(p)
    fmt.Println("rp:", rp)

    for i := 0; i < rp.NumField(); i++ {
        fmt.Printf("%s: Pointer: %d CanSet: %t\n", rp.Type().Field(i).Name, rp.Field(i).Pointer(), rp.Field(i).Elem().CanSet())
    }

    rp.Field(0).Elem().SetString("Brian")
    fmt.Println(*p.FirstName)

    // Yields nil pointer error
    // rp.Field(1).Elem().SetString("Johnson")
    // fmt.Println(*p.LastName)

    fmt.Println(rp.Field(1).Type()) 
    fmt.Println(rp.Field(1).CanSet())
    // fmt.Println(rp.Field(1).Elem().Type()) // nil pointer here also
    fmt.Println(rp.Field(1).Elem().CanSet())
}
Run Code Online (Sandbox Code Playgroud)

在Golang Playground看到

Jim*_*imB 7

首先需要一个指向a的指针Person{},因为你需要为LastNameField 设置一个值.

p := &Person{}
Run Code Online (Sandbox Code Playgroud)

然后,您可以为该LastName字段设置有效的指针值,这将允许您设置字符串值:

rp.Field(1).Set(reflect.New(rp.Field(1).Type().Elem()))
rp.Field(1).Elem().SetString("Jones")
Run Code Online (Sandbox Code Playgroud)

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