LoginSignup
2
1

More than 3 years have passed since last update.

ネストしているstruct内のすべての値を取得し、文字列連結する

Last updated at Posted at 2020-02-03

目的

ネストしているstruct内のすべての値を取得し、文字列連結したい

ユースケース

連結した文字列からハッシュを生成し、リクエストパラメータのチェックサムに使う

コード

package main

import (
    "bytes"
    "fmt"
    "reflect"
    "strconv"
)

// reflect.Value を返す関数
func toReflectValue(i interface{}) (reflect.Value, bool) {
    rv, ok := i.(reflect.Value)
    if !ok {
        rv = reflect.ValueOf(i)
    }

    switch rv.Kind() {
    case reflect.Ptr:
        // ポインタ以外になるまで reflect.Indirect する
        return toReflectValue(reflect.Indirect(rv))
    case reflect.Struct:
        return rv, true
    }
    // 構造体以外
    return rv, false
}

func recursive(depth int, rv reflect.Value, str *bytes.Buffer) {
    typ := rv.Type()

    for i := 0; i < typ.NumField(); i++ {
        field := typ.Field(i)
        kind := field.Type.Kind()
        value := rv.FieldByName(field.Name)
        if kind != reflect.Ptr {
            if kind == reflect.Struct {
                recursive(depth+1, value, str)
            } else {
                switch kind.String() {
                case "int":
                    s := value.Interface().(int)
                    str.WriteString(strconv.Itoa(s))
                case "string":
                    str.WriteString(value.String())
                }

            }
        }
    }
}

func main() {
    type Address struct {
        name string
    }

    type User struct {
        Name    string
        Age     int
        Address Address
    }

    user := User{"suzuki", 18, Address{"Tokyo"}}
    rv, _ := toReflectValue(user)
    str := bytes.Buffer{}
    recursive(0, rv, &str)
    fmt.Println(str.String())
}

結果

suzuki18Tokyo

その他

他の型への対応は、switch kind.String()に追加する

参考

下記のコードに対して修正を加えました。感謝 :pray: :pray: :pray:
https://golang.hateblo.jp/entry/2018/11/10/083000

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1