Skip to content

Instantly share code, notes, and snippets.

@Mo3g4u
Created August 22, 2022 04:24
Show Gist options
  • Save Mo3g4u/9129e1ad76627cabf14d067d28bb2f1d to your computer and use it in GitHub Desktop.
Save Mo3g4u/9129e1ad76627cabf14d067d28bb2f1d to your computer and use it in GitHub Desktop.
タグを使った構造体へのデータの書き込み
package main
// タグを使った構造体へのデータの書き込み
import (
"fmt"
"reflect"
"strconv"
)
// reflect.Value:値、ポインターなどを扱うデータ型
// reflect.Type:型を扱うデータ型
type MapStruct struct {
Str string `map:"str"`
StrPtr *string `map:"str"`
Bool bool `map:"bool"`
BoolPtr *bool `map:"bool"`
Int int `map:"int"`
IntPtr *int `map:"int"`
}
func main() {
src := map[string]string{
"str": "string data",
"bool": "true",
"int": "12345",
}
var ms MapStruct
Decode(&ms, src)
fmt.Printf("%#v\n", ms)
}
func Decode(target interface{}, src map[string]string) error {
v := reflect.ValueOf(target)
e := v.Elem()
return decode(e, src)
}
func decode(e reflect.Value, src map[string]string) error {
t := e.Type()
for i := 0; i < t.NumField(); i++ {
f := t.Field(i)
// 埋め込まれた構造体は再帰処理
if f.Anonymous {
if err := decode(e.Field(i), src); err != nil {
return err
}
continue
}
// 子供が構造体だったら再帰処理
if f.Type.Kind() == reflect.Struct {
if err := decode(e.Field(i), src); err != nil {
return err
}
continue
}
// タグがなければフィールド名をそのまま使う
key := f.Tag.Get("map")
if key == "" {
key = f.Name
}
// 元データになければスキップ
sv, ok := src[key]
if !ok {
continue
}
// フィールドの型を取得
var k reflect.Kind
var isP bool
if f.Type.Kind() != reflect.Ptr {
k = f.Type.Kind()
} else {
k = f.Type.Elem().Kind()
// ポインターのポインターは無視
if k == reflect.Ptr {
continue
}
isP = true
}
switch k {
case reflect.String:
if isP {
e.Field(i).Set(reflect.ValueOf(&sv))
} else {
e.Field(i).SetString(sv)
}
case reflect.Bool:
b, err := strconv.ParseBool(sv)
if err == nil {
if isP {
e.Field(i).Set(reflect.ValueOf(&b))
} else {
e.Field(i).SetBool(b)
}
}
case reflect.Int:
n64, err := strconv.ParseInt(sv, 10, 64)
if err == nil {
if isP {
n := int(n64)
e.Field(i).Set(reflect.ValueOf(&n))
} else {
e.Field(i).SetInt(n64)
}
}
}
}
return nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment