Heim > Backend-Entwicklung > Golang > Ausführliche Erklärung von Golangs Reflexion (Beispiel)

Ausführliche Erklärung von Golangs Reflexion (Beispiel)

藏色散人
Freigeben: 2020-09-08 09:21:23
nach vorne
3972 Leute haben es durchsucht

Das Folgende ist eine detaillierte Erklärung von Golangs Reflexion (Beispiel) aus der Kolumne Golang-Tutorial. Ich hoffe, dass es Freunden in Not hilfreich sein wird!

Ausführliche Erklärung von Golangs Reflexion (Beispiel)

Vorwort

Reflection hat in vielen Sprachen seine wunderbaren Einsatzmöglichkeiten. In der Informatik bezeichnet Reflexion eine Klasse von Anwendungen, die selbstbeschreibende Angriffe und selbstkontrollierende Angriffe ermöglichen.

In diesem Artikel werden die Anmerkungen des Autors zu Golangs Reflexion aufgezeichnet.

Nach 10 Sekunden liegen Ihnen die folgenden Wissenspunkte nahe:
1. Einführung in die Reflexion
2.
3. Was genau Reflexion bewirken kann?

,

Methoden aufrufen

und direkt auf deren

Layout

einwirken, wird als Reflektion bezeichnet.

2. Warum Reflexion nutzen? Manchmal benötigen wir beispielsweise eine Funktion, die verschiedene Arten von Werten verarbeiten kann. Ohne den Typ zu kennen, könnten Sie schreiben:

// 伪代码
switch value := value.(type) {
case string:
	// ...一些操作
case int:	
	// ...一些操作	
case cbsStruct: // 自定义的结构体	
	// ...一些操作

// ...
}
Nach dem Login kopieren
Haben Sie irgendwelche Probleme festgestellt? Hier gibt es ein Problem: Es gibt viele Typen, das Schreiben dieser Funktion wird sehr lange dauern, und es kann auch benutzerdefinierte Typen geben, was bedeutet, dass dieses Urteil möglicherweise in Zukunft geändert werden muss, da dies unmöglich ist wissen, zu welchem ​​Typ der unbekannte Wert gehört. Wenn Sie einen unbekannten Typ nicht durchschauen können, ist der obige Code tatsächlich nicht sehr sinnvoll. Zu diesem Zeitpunkt benötigen Sie

Reflection

, um damit umzugehen.

Reflection verwendet die Funktionen TypeOf und ValueOf Zielobjekt über die Benutzeroberfläche aufrufen und den Zweck problemlos erfüllen

.

3. Was genau kann Reflexion bewirken? ?? Eingabe abrufen Der Wert der Daten in der Parameterschnittstelle wird zurückgegeben
0 <- Beachten Sie, dass es 0 ist.Reflect.TypeOf()

Erhält dynamisch den Typ des Werts in Eingabeparameterschnittstelle. Wenn sie leer ist, wird

Null < zurückgegeben. Beachten Sie, dass es Null ist Die „Variable des Schnittstellentyps“ wird in die Variable „Reflektierter Schnittstellentyp“ umgewandelt. Das Obige gibt beispielsweise tatsächlich die Schnittstellenobjekte „reflect.Value“ und „reflect.Type“ zurück. (Sie können dies ermitteln, indem Sie den Rückgabetyp der relevanten Funktion gemäß der IDE verfolgen.) 2. Reflexion der Struktur

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)
}
Nach dem Login kopieren

Ausgabe:
type:  string
value:  咖啡色的羊驼
Nach dem Login kopieren

3. Reflexion anonymer oder eingebetteter Felder

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)
	}
}
Nach dem Login kopieren

Ausgabe:
这个类型的名称是: Student
第1个字段是:Id:int = 1 
第2个字段是:Name:string = 咖啡色的羊驼 
第1个方法是:Hello:func(main.Student)
Nach dem Login kopieren
4 .Bestimmen Sie, ob der eingehende Typ der von uns gewünschte Typ ist
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))
}
Nach dem Login kopieren
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:"咖啡色的羊驼"}
Nach dem Login kopieren
5. Ändern Sie den Inhalt durch Reflexion
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")
	}
}
Nach dem Login kopieren
bingo
bingo
Nach dem Login kopieren
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)
}
Nach dem Login kopieren
Ausgabe:
main.Student{Id:1, Name:"小学生"} 
666
Nach dem Login kopieren
Ausgabe:
Ausgabe: 6 Methode durch Reflexion
##4. Bei der Verwendung von Reflektion müssen Sie zunächst feststellen, ob der zu bedienende Wert vom erwarteten Typ ist und ob er „zugeordnet“ werden kann. , sonst funktioniert das Reflect-Paket nicht und erzeugt gnadenlose Panik. 2. Reflexion hängt hauptsächlich mit dem Schnittstellentyp von Golang zusammen. Nur Schnittstellentypen verfügen über Reflexion. Wenn Sie interessiert sind, können Sie einen Blick auf TypeOf und ValueOf werfen. Sie werden feststellen, dass die Parameter bei der Übergabe in Schnittstellentypen konvertiert wurden.
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)
}
Nach dem Login kopieren

Das obige ist der detaillierte Inhalt vonAusführliche Erklärung von Golangs Reflexion (Beispiel). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:csdn.net
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage