40

そのため、Go (golang) でリフレクションを開始するのに役立つコードを見つけましたが、基になる値を取得するのに問題があるため、基本的にmap[string]string構造体とフィールドから を作成できます。

最終的には、結果を にしたいのですmap[string]interface{}が、この 1 つの問題が私を妨げています。

私が現時点で持っているコード:

package main

import (
    "fmt"
    "reflect"
)

type Foo struct {
    FirstName string `tag_name:"tag 1"`
    LastName  string `tag_name:"tag 2"`
    Age       int  `tag_name:"tag 3"`
}

func inspect(f interface{}) map[string]string {

    m := make(map[string]string)
    val := reflect.ValueOf(f).Elem()

    for i := 0; i < val.NumField(); i++ {
        valueField := val.Field(i)
        typeField := val.Type().Field(i)

        f := valueField.Interface()
        val := reflect.ValueOf(f)
        m[typeField.Name] = val.String()
    }

    return m
}

func dump(m map[string]string) {

    for k, v := range m {
        fmt.Printf("%s : %s\n", k, v)
    }
}

func main() {
    f := &Foo{
        FirstName: "Drew",
        LastName:  "Olson",
        Age:       30,
    }

    a := inspect(f)

    dump(a)
}

コードの実行による出力:

FirstName : Drew
LastName : Olson
Age : <int Value>

私が理解していることから、FirstName と LastName の出力は実際の Reflect.Value オブジェクトですが、文字列の場合、値の String() メソッドは基になる文字列を出力するだけです。int を取得して文字列に変更したいのですが、refect パッケージのドキュメントからは、それがどのように行われたのかすぐにはわかりません。

スー.... golangのreflect.Valueから基になる値を取得するにはどうすればよいですか?

4

4 に答える 4

24

値を解析する方法の良い例はfmtパッケージです。このコードを参照してください。

上記のコードを使用して問題に一致させると、次のようになります。

switch val.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
    m[typeField.Name] = strconv.FormatInt(val.Int(), 10)
case reflect.String:
    m[typeField.Name] = val.String()    
// etc...
}

基本的に、利用可能なすべての Kindsを確認する必要があります。

于 2013-08-07T17:14:16.777 に答える
2

これは、Go 1.5 (2015 年 8 月) で簡単に実行できるはずです。レビュー 8731を参照し、 Rob Pike ( )によるコミット 049b89d :robpike

fmt: 特別に扱うreflect.Value- 保持する値として

Reflect.Value()これにより、引数の実際の値を出力できます。

aが(など) にreflect.Value渡されると、メソッドが呼び出されますが、その内容は公開されません。 コンテンツを取得するには、 を呼び出すことができますが、 がエクスポートされていないか、禁止されている場合、これは違法です。PrintffmtString
Value.Interface()Value

この CL は、パッケージに些細な変更を加えることで状況を改善します。引数としてfmta を見ると、パッケージ内で作成しreflect.Valueた a を扱うのとまったく同じように扱いreflect.Valueます。これは、あたかもそれが への引数であるかのよう
に、常に の内容を出力することを意味します。ValuePrintf

これは間違いなく重大な変更ですが、これは真の改善であり、このパッケージからフォーマットされた出力に対して行った他の多くの調整よりも大きなブレークではないと思います.

于 2015-04-16T08:06:32.533 に答える