0
Goのリフレクションパッケージを使用すると、ポインタがnilの場合に構造体にポインタを設定する方法はありますか?反射パッケージを見ると、reflect.Value.CanSet()
がfalse
の場合、Set()
の呼び出しはパニックになります。これを回避する別の方法は、構造体への直接参照に依存せず、リフレクトパッケージを使用するだけですか?たとえば、以下のコードで空の姓を "Johnson"に設定するにはどうすればよいですか?あなたはLastName
フィールドに値を設定する必要があるためGolangは、構造体にnil文字列ポインタ値を設定します。
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())
}
:
次に、あなたが文字列値を設定することができます
LastName
フィールドに有効なポインタ値を設定することができます。 ..なぜあなたはこれをしたいですか?私は自分自身が文字列へのポインタを使用する理由の多くを見たことがなく、標準ライブラリで使用されているのを見たこともありません。 – RayfenWindspear公正な質問。 REST APIを公開すると、クライアントがフィールドを提供したかどうかを知ることができます。それらがポインタでない場合、文字列の空の値は '' ''です。それから、私はクライアントに '' ''を提供したのか、それとも何も提供しなかったのかを尋ねなければならないでしょうか?さらに、 'Validate'や' Transform'のような構造体フィールドに一意のタグを追加しています。だから、私はそれらを解析するために反射パッケージを使用しています。 –