Go 言語構造リフレクションの基本を説明する記事

リリース: 2023-07-21 10:14:59
転載
994 人が閲覧しました

リフレクションの構造への応用

前回話したのは普通の変数だけの応用, 比較的、使用シーンはそれほど多くありません。

ただし、構造内での リフレクションの適用は、基本的に Go 言語の基盤全体で実行されます。

サンプルコード

構造

type Student struct {
    Name   string   `json:"name" describe:"姓名"`
    Age    int      `json:"age" describe:"年龄"`
    Gender bool     `json:"gender" describe:"性别"`
    Hobby  []string `json:"hobby" describe:"爱好"`
}
ログイン後にコピー

main

func main() {
    //实例化结构体
    var s1 = Student{
        Name:   "张三",
        Age:    18,
        Gender: true,
        Hobby:  []string{"吃", "喝", "pia", "玩"},
}
    var t = reflect.TypeOf(s1)
    fmt.Println(t.Name())     //Student
    fmt.Println(t.Kind())     //struct
    fmt.Println(t.NumField()) //结果:4,表示多少个字段
    for i := 0; i < t.NumField(); i++ {
        field := t.Field(i)//每个结构体对象
        /*
            {Name  string json:"name" describe:"姓名" 0 [0] false}
            {Age  int json:"age" describe:"年龄" 16 [1] false}
            {Gender  bool json:"gender" describe:"性别" 24 [2] false}
            {Hobby  []string json:"hobby" describe:"爱好" 32 [3] false}
        */
        //fmt.Println(field)
        fmt.Println("------")
        fmt.Printf("field.Name:%v\n",field.Name)
        fmt.Printf("field.Index:%v\n",field.Index)
        fmt.Printf("field.Type:%v\n",field.Type)
        fmt.Printf("field.Tag:%v\n",field.Tag.Get("describe"))


    }
}
ログイン後にコピー

実行結果


单独反射指定字段信息

main代码

func main() {
    //实例化结构体
    var s1 = Student{
        Name:   "张三",
        Age:    18,
        Gender: true,
        Hobby:  []string{"吃", "喝", "pia", "玩"},
}
    var t = reflect.TypeOf(s1)
    genderField, ok := t.FieldByName("Gender")
    if ok {
        fmt.Println(genderField.Name)                //Gender
        fmt.Println(genderField.Index)               //[2]
        fmt.Println(genderField.Type)                //bool
        fmt.Println(genderField.Tag.Get("describe")) //性别
    }
}
ログイン後にコピー

ValueOf

上述的代码只能用的是TypeOf,只能返回类型等信息,相对来说不是太智能,ValueOf可以获取值,同样也能获取类型,相对来说比TypeOf好一点。

示例代码

main

func main() {
    //实例化结构体
    var s1 = Student{
        Name:   "张三",
        Age:    18,
        Gender: true,
        Hobby:  []string{"吃", "喝", "pia", "玩"},
}
    var v = reflect.ValueOf(s1)
    for i := 0; i < v.NumField(); i++ {
        field :=v.Field(i)
        fmt.Println("------")
        fmt.Printf("Kind:%v\n",field.Kind())
        fmt.Printf("值:%v\n",field.Interface())
    }
}
ログイン後にコピー

执行结果

Go 言語構造リフレクションの基本を説明する記事


反射方法

上述我们反射的都是值,有没有反射是否可以反射函数,并且调用函数呢??

结构体和绑定函数代码

type Student struct {
    Name   string   `json:"name" describe:"姓名"`
    Age    int      `json:"age" describe:"年龄"`
    Gender bool     `json:"gender" describe:"性别"`
    Hobby  []string `json:"hobby" describe:"爱好"`
}


//无参方法
func (this Student) Say() {
    fmt.Printf("我是%v,我的年龄是%v,我的性别是%v,我的爱好是%v\n", this.Name, this.Age, this.Gender, this.Hobby)
}
//有参数方法
func (this Student) Jump(distance int) {
    fmt.Printf("我是%v,我跳远跳了%v米\n", this.Name, distance)
}
ログイン後にコピー

main

func main() {
    //实例化结构体
    var s1 = Student{
        Name:   "张三",
        Age:    18,
        Gender: true,
        Hobby:  []string{"吃", "喝", "pia", "玩"},
}
    var t = reflect.TypeOf(s1)
    var v = reflect.ValueOf(s1)
    fmt.Println(v.NumMethod(),v.NumField())
    for i := 0; i < v.NumMethod(); i++ {
        method := v.Method(i)
        fmt.Println("--------")
        fmt.Println(method)//0x48c4e0 函数地址
        fmt.Println(method.Type())//func(int) 函数类型,形参和返回值
        fmt.Println(t.Method(i).Name)//Jump,函数名,注意,由t来调用的
    }
}
ログイン後にコピー

执行结果

Go 言語構造リフレクションの基本を説明する記事


反射调用函数

func main() {
    //实例化结构体
    var s1 = Student{
        Name:   "张三",
        Age:    18,
        Gender: true,
        Hobby:  []string{"吃", "喝", "pia", "玩"},
}
    var v = reflect.ValueOf(s1)


    //通过反射调用函数
    //调用Jump函数
    //反射调用函数必须传一个参数,不管有没有形参都要传
    //var args = []reflect.Value{}
    //v.MethodByName("Say").Call(args)


    //如果需要传参数
    //参数需要用reflect.ValueOf(1) 强转一下


    var args = []reflect.Value{reflect.ValueOf(2)}
    v.MethodByName("Jump").Call(args)
}
ログイン後にコピー

注:注意第14行和20行代码区别,如果要传参数,参考第20行代码。

执行结果

Go 言語構造リフレクションの基本を説明する記事


反射注意事项

在平常开发中,尽量慎用反射,原因如下。

  • 反射性能は比較的低いかもしれませんが、やはり順方向に進むため、通常は順方向に比べて 1 ~ 2 段階遅くなります。

  • リフレクションが多ければ多いほど、コードは悪化します。TypeOf ValueOf# には Kind があり、多くの場合 ## です#TypeOf ValueOf が混在しているため、基礎が苦手な人には非常に不親切です。

  • Go では、リフレクションが処理されない場合、

    #try はありません。例外として、プログラムは予期しない場所で直接クラッシュします。

  • ##概要

# 上記では主に Go# について説明しました。

##反射構造関連知識 ( を含む)

    構造への反射の適用
  • #構造体フィールド情報を個別に反映する方法

  • ##その他の操作の値

  • 構造結合法を放射する方法

以上がGo 言語構造リフレクションの基本を説明する記事の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:Go语言进阶学习
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート