ホームページ  >  記事  >  バックエンド開発  >  リフレクションでネストされた構造を参照によって渡し、デフォルト値を再帰的に設定するにはどうすればよいですか?

リフレクションでネストされた構造を参照によって渡し、デフォルト値を再帰的に設定するにはどうすればよいですか?

DDD
DDDオリジナル
2024-10-24 02:22:29372ブラウズ

How to Pass Nested Structures by Reference in Reflection and Set Default Values Recursively?

リフレクションによる参照によるネストされた構造の受け渡し

リフレクションによるネストされた構造の走査と変更により、データの動的な操作が可能になります。ただし、それ自体が構造体である構造体フィールドに遭遇した場合、リフレクションを使用して値を設定すると、「reflect.Value.Set using unaddressable value」パニックが発生する可能性があります。

問題の理解

問題の根本は、リフレクションが入れ子になった構造を処理する方法にあります。デフォルトでは、構造体は値によって渡されます。つまり、変更のためにネストされた構造体フィールドから値を取得するとき、元のデータではなくデータのコピーを操作することになります。加えられた変更はコピーにのみ影響し、実際の構造には影響しません。

解決策: 参照による受け渡し

ネストされた構造体のフィールド値を設定するには、次の値を渡す必要があります。それをポインタとして使用します。これは、実際の構造体の値へのポインタを返す Value.Addr() メソッドを使用して実現できます。

再帰的なデフォルト値の設定

サンプル内の再帰コードは、構造体とそのネストされた構造体のすべてのフィールドを走査する必要性を反映しています。デフォルト値を設定するには、各フィールドのポインター値に対して setDefaultValue を呼び出します。プリミティブ型 (int、string、bool) の場合、デフォルト値はハードコードされています。ネストされた構造体の場合、フィールドを処理するために setDefaultValue が再帰的に呼び出されます。

作業例

次のサンプル コードを考えてみましょう。

<code class="go">type Client struct {
    Id                int
    Age               int
    PrimaryContact    Contact
    Name              string
}

type Contact struct {
    Id        int
    ClientId  int
    IsPrimary bool
    Email     string
}

func SetDefault(s interface{}) error {
    return setDefaultValue(reflect.ValueOf(s))
}

func setDefaultValue(v reflect.Value) error {

    if v.Kind() != reflect.Ptr {
        return errors.New("Not a pointer value")
    }

    v = reflect.Indirect(v)
    switch v.Kind() {
        case reflect.Int:
            v.SetInt(42)
        case reflect.String:
            v.SetString("Foo")
        case reflect.Bool:
            v.SetBool(true)
        case reflect.Struct:
            // Iterate over the struct fields
            for i := 0; i < v.NumField(); i++ {
                err := setDefaultValue(v.Field(i).Addr())
                if err != nil {
                    return err
                }
            }       

        default:
            return errors.New("Unsupported kind: " + v.Kind().String())

    }

    return nil  
}


func main() {
    a := Client{}
    err := SetDefault(&a)
    if err != nil {
        fmt.Println("Error: ", err)
    } else {
        fmt.Printf("%+v\n", a)
    }
}</code>

出力:

{Id:42 Age:42 PrimaryContact:{Id:42 ClientId:42 IsPrimary:true Email:Foo} Name:Foo}

この例では、再帰を使用してデフォルト値を設定し、リフレクションを通じてネストされた構造を参照によって渡す方法を示します。

以上がリフレクションでネストされた構造を参照によって渡し、デフォルト値を再帰的に設定するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。