前提・実現したいこと
reflectの動きを理解すること。その手段として、次のようなお題を立てました。
<お題>
{"key1": []} というJSONをjson.unmarshalでinterface[]に取り込み、その結果を引数として受け取り、{"key1": [“update”]} に変更する関数「Add」を作成する。
発生している問題・エラーメッセージ
下記のコードの※1の箇所で次のエラーが発生します。
panic: reflect: reflect.Value.Set using unaddressable value
該当のソースコード
package main import ( "fmt" "encoding/json" "reflect" ) func main() { strDst := `{"key1": []}` strAdd := `"update"` var objDst interface{} var objAdd interface{} json.Unmarshal(([]byte)(strDst), &objDst) json.Unmarshal(([]byte)(strAdd), &objAdd) Add(&objDst, objAdd) } func Add(dst interface{}, add interface{}){ v := reflect.ValueOf(dst).Elem() // Merge()で宣言したobjDstのポインタ v = v.Elem().MapIndex(reflect.ValueOf("key1")) // ※2 多段構成に対応するため fmt.Println(v.Kind(), v.Elem().Kind()) // それぞれinterface, slice fmt.Println(v.Elem().Len()) // 0と表示される if v.Elem().Len() == 0 { sr := reflect.ValueOf(reflect.ValueOf(add)) v.Set(reflect.Append(v.Elem(), sr)) // ※1 } fmt.Println(v) // 以下省略 }
以下の質問に対するご回答としてmattnさんから頂いたコードをベースとしております。
https://teratail.com/questions/106644
試したこと
コードの ※2 の行をコメントアウトすれば、以下のようなシンプルな追加処理を行えることを確認しました。
成功したケースの例:
JSON [] に対する “update” の追加(追加の結果は[update])
https://blog.golang.org/laws-of-reflection にも書かれている通り、ポインタに対するreflect.valueであればSetが機能するため、期待通り動作するのだと思います(関数Addはポインタを引数で受け取っている) しかし、多段構成のJSONに対応するには ※2 のような処理でObjectから配列を取り出す必要がありますが、この処理で得られるvはポインタではないため、Setが機能しないものと理解しています。
質問
上記のようなケースにおいて、Setを実行するためにアドレス可能な値を得るにはどのようにすればよいでしょうか? あるいは配列に値を追加するSet以外の方法があれば、そちらでも構いません。お手数ですが、よろしくお願いいたします。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/12/29 12:57
2018/01/07 09:21