# 振り返り(例)、困っている友達のお役に立てれば幸いです。 序文
リフレクションは、多くの言語で素晴らしい用途を持っています。コンピューター サイエンスでは、リフレクションとは、自己記述型攻撃と自己制御型攻撃を可能にするアプリケーションのクラスを指します。 この記事は、Golang の考察に関する著者のメモを記録します。 10 秒後には、次の知識ポイントが得られるようになります:1. リフレクションの概要
2. リフレクションを使用する理由3. リフレクションで正確にできること
1. リフレクションの概要Golang は、コンパイル時に が型を認識しないメカニズムを提供します
の場合、、メソッドを呼び出しこのメカニズムはリフレクションと呼ばれます。 2.なぜリフレクションを使用するのでしょうか?、その
レイアウトを直接操作できます
何か問題は見つかりましたか? | ここには問題があります | : 多くの型があり、この関数を記述するのは非常に長くなり、カスタム型も存在する可能性があります。つまり、将来この判断を変更する必要がある可能性があります。 、値がどの型に属するかを知る方法がないためです。
---|---|
Reflection では、インターフェイスから TypeOf 関数と ValueOf 関数を使用して対象オブジェクトの情報を取得し、目的を簡単に完了できます | 。3. リフレクションでは具体的に何ができるのでしょうか? |
reflect は、インターフェイス変数の内容にアクセスするための 2 つのタイプを提供します: |
を返します <- 0入力パラメータ インターフェイスのデータの値を取得する空の場合は、
0
の値を動的に取得します。入力パラメータ インターフェイス Type、空の場合はreflect.TypeOf()
nil
を返します <- nil であることに注意してください##上記のコード
package main import ( "fmt" "reflect" ) func main() { var name string = "咖啡色的羊驼" // TypeOf会返回目标数据的类型,比如int/float/struct/指针等 reflectType := reflect.TypeOf(name) // valueOf返回目标数据的的值,比如上文的"咖啡色的羊驼" reflectValue := reflect.ValueOf(name) fmt.Println("type: ", reflectType) fmt.Println("value: ", reflectValue) }出力:
type: string value: 咖啡色的羊驼より深い: 上記の操作が発生すると、リフレクションは「インターフェイス型変数」を「リフレクトされたインターフェイス型変数」に変換します。たとえば、上記は実際には、reflect.Value とreflect.Type のインターフェイスを返します。 。 物体。 (IDE に従って、関連する関数の戻り値の型を追跡することで知ることができます)
2.構造体の反映
package main import ( "fmt" "reflect" ) type Student struct { Id int Name string } func (s Student) Hello(){ fmt.Println("我是一个学生") } func main() { s := Student{Id: 1, Name: "咖啡色的羊驼"} // 获取目标对象 t := reflect.TypeOf(s) // .Name()可以获取去这个类型的名称 fmt.Println("这个类型的名称是:", t.Name()) // 获取目标对象的值类型 v := reflect.ValueOf(s) // .NumField()来获取其包含的字段的总数 for i := 0; i < t.NumField(); i++ { // 从0开始获取Student所包含的key key := t.Field(i) // 通过interface方法来获取key所对应的值 value := v.Field(i).Interface() fmt.Printf("第%d个字段是:%s:%v = %v \n", i+1, key.Name, key.Type, value) } // 通过.NumMethod()来获取Student里头的方法 for i:=0;i<t.NumMethod(); i++ { m := t.Method(i) fmt.Printf("第%d个方法是:%s:%v\n", i+1, m.Name, m.Type) } }出力:
这个类型的名称是: Student 第1个字段是:Id:int = 1 第2个字段是:Name:string = 咖啡色的羊驼 第1个方法是:Hello:func(main.Student)
3 .匿名フィールドまたは埋め込みフィールドの反映
package main import ( "reflect" "fmt" ) type Student struct { Id int Name string } type People struct { Student // 匿名字段 } func main() { p := People{Student{Id: 1, Name: "咖啡色的羊驼"}} t := reflect.TypeOf(p) // 这里需要加一个#号,可以把struct的详情都给打印出来 // 会发现有Anonymous:true,说明是匿名字段 fmt.Printf("%#v\n", t.Field(0)) // 取出这个学生的名字的详情打印出来 fmt.Printf("%#v\n", t.FieldByIndex([]int{0, 1})) // 获取匿名字段的值的详情 v := reflect.ValueOf(p) fmt.Printf("%#v\n", v.Field(0)) }出力:
reflect.StructField{Name:"Student", PkgPath:"", Type:(*reflect.rtype)(0x10aade0), Tag:"", Offset:0x0, Index:[]int{0}, Anonymous:true} reflect.StructField{Name:"Name", PkgPath:"", Type:(*reflect.rtype)(0x109f4e0), Tag:"", Offset:0x8, Index:[]int{1}, Anonymous:false} main.Student{Id:1, Name:"咖啡色的羊驼"}
4.受信した型が必要な型であるかどうかを判断します
出力:package main import ( "reflect" "fmt" ) type Student struct { Id int Name string } func main() { s := Student{Id: 1, Name: "咖啡色的羊驼"} t := reflect.TypeOf(s) // 通过.Kind()来判断对比的值是否是struct类型 if k := t.Kind(); k == reflect.Struct { fmt.Println("bingo") } num := 1; numType := reflect.TypeOf(num) if k := numType.Kind(); k == reflect.Int { fmt.Println("bingo") } }
bingo bingo######5. リフレクションによるコンテンツの変更######
package main import ( "reflect" "fmt" ) type Student struct { Id int Name string } func main() { s := &Student{Id: 1, Name: "咖啡色的羊驼"} v := reflect.ValueOf(s) // 修改值必须是指针类型否则不可行 if v.Kind() != reflect.Ptr { fmt.Println("不是指针类型,没法进行修改操作") return } // 获取指针所指向的元素 v = v.Elem() // 获取目标key的Value的封装 name := v.FieldByName("Name") if name.Kind() == reflect.String { name.SetString("小学生") } fmt.Printf("%#v \n", *s) // 如果是整型的话 test := 888 testV := reflect.ValueOf(&test) testV.Elem().SetInt(666) fmt.Println(test) }###出力: ###
main.Student{Id:1, Name:"小学生"} 666######6. メソッドの呼び出しリフレクションによる# #####
package main import ( "fmt" "reflect" ) type Student struct { Id int Name string } func (s Student) EchoName(name string){ fmt.Println("我的名字是:", name) } func main() { s := Student{Id: 1, Name: "咖啡色的羊驼"} v := reflect.ValueOf(s) // 获取方法控制权 // 官方解释:返回v的名为name的方法的已绑定(到v的持有值的)状态的函数形式的Value封装 mv := v.MethodByName("EchoName") // 拼凑参数 args := []reflect.Value{reflect.ValueOf("咖啡色的羊驼")} // 调用函数 mv.Call(args) }###出力: ###
我的名字是: 咖啡色的羊驼#####4. リフレクションの小さなポイント######1. リフレクションを使用する場合、最初に値が操作対象は期待されるタイプであり、「割り当て」操作を実行できるかどうか、そうでない場合は、reflect パッケージが容赦なくパニックを生成します。 ######2. リフレクションは主に Golang のインターフェイス タイプに関連しており、インターフェイス タイプのみがリフレクションを持ちます。興味があれば、TypeOf と ValueOf を見てみると、パラメーターが渡されるときにインターフェース型に変換されていることがわかります。 ###rreeee#########
以上がGolangのリフレクションの詳しい説明(例)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。