Механизм отражения Go Reflect

Java задняя часть Go
Справочная статья:

Принцип реализации пакета отражения на языке Go (Законы отражения)

Как и язык Java, Go также реализует отражение во время выполнения, что дает нам возможность манипулировать объектами любого типа во время выполнения. Go статически типизирован. Каждая переменная имеет статический тип, то есть тип переменной точно определяется во время компиляции, например, либо int, либо float32, либо MyType, либо []byte и т.д.

1. Первый закон отражения (отражение значений интерфейса к отражающим объектам) TypeOf и ValueOf

В определении отражения Go любой интерфейс будет состоять из двух частей: одна — конкретный тип интерфейса, а другая — значение, соответствующее конкретному типу. Напримерvar i int = 3,так какinterface{}может представлять любой тип, поэтому переменнаяiможет быть преобразован вinterface{}, поэтому переменная может бытьiВ качестве интерфейса представление этой переменной в отражении Go будет<Value,Type>, где Значение — значение переменной3, переменная Type — это типint.

Reflect.Typeof получает конкретный тип, Reflect.Valueof получает значение интерфейса.

type Myint int

type User struct {
	name string 
	age int
}

func main() {
	u := User{name:"lyd",age:24}
	var num Myint = 18
	t := reflect.TypeOf(u)        //main.User
	v := reflect.ValueOf(u)       //{lyd 24}
        t_num := reflect.TypeOf(num)  //main.Myint
        v_num := reflect.ValueOf(num) //18
}
//还可以这样打印
fmt.Printf("%T\n",u)
fmt.Printf("%v\n",u)
v.Type() //main.User

2. Преобразование Reflect.Value в примитивный тип (второй закон отражения)

В приведенном выше примере мы можем передатьreflect.ValueOfФункция преобразует объект любого типа вreflect.Value, учитывая значение Reflect.Value, мы можем использовать метод интерфейса, чтобы восстановить его до значения интерфейса;

type Myint int

type User struct {
	name string 
	age int
}

func main() {
	u := User{name:"lyd",age:24}
	var num Myint = 18
	v := reflect.ValueOf(u) 
	v_num := reflect.ValueOf(num)

	y := v.Interface().(User)
	//fmt.Println可以处理interface{}, 所以可以直接
	y_num := v_num.Interface()

	fmt.Println(y,y_num) //{lyd 24} 18 

}

3. Изменить значение отражающего объекта (третий закон отражения)

reflect.ValueOfФункция возвращает копию значения, поэтому предполагается, что мы передаем адрес изменяемой переменной. Во-вторых, нам нужно позвонитьElemметод, чтобы найти значение, на которое указывает этот указатель.

Valueпредоставляет намCanSetЭтот метод может помочь нам оценить возможность установки значения.

Один: объект отражения не устанавливается

func main() {
	var x float64 = 3.4
	v := reflect.ValueOf(x)
	v.SetFloat(7.1) // Error: will panic.
}

func main() {
	var x float64 = 3.4
	v := reflect.ValueOf(x)
	fmt.Println("settability of v:", v.CanSet())  //settability of v: false
}

var x float64 = 3.4
p := reflect.ValueOf(&x) // Note: take the address of x.注意这里哦!我们把x地址传进去了!
fmt.Println("type of p:", p.Type())  // type of p: *float64
fmt.Println("settability of p:", p.CanSet())  //settability of p: false

Объект отражения p нельзя установить, но мы хотим установить не p, а (фактически) *p. Чтобы получить то, на что указывает p, мы вызываем метод Elem класса Value.

Два: Короче говоря, следующий способ изменить значение

func main() {
	x:=2
	v:=reflect.ValueOf(&x)
	v.Elem().SetInt(100)
	fmt.Println(x)
}

4. Получите базовый тип

type User struct {
	name string 
	age int
}

func main() {
	u := User{name:"lyd",age:24}
	t := reflect.TypeOf(u)        
	v := reflect.ValueOf(u)      
	fmt.Println(t.Kind(),v.Kind()) //struct struct
}

5. Поля и методы обхода

Через отражение мы можем получить поля структурного типа, а также можем получить метод экспорта типа

type User struct {
	name string 
	age int
}

func main() {
	u := User{name:"lyd",age:24}
	t := reflect.TypeOf(u)        
	for i:=0;i<t.NumField();i++ {
		fmt.Println(t.Field(i).Name) 
	}
}
//name
//age

//方法
for i:=0;i<t.NumMethod() ;i++  {
	fmt.Println(t.Method(i).Name)
}

6. Метод динамического вызова


7, строковый объект JSON и преобразование структуры

a: строка JSON для структуры

type User struct {
	Name string 
	Age int 
}

func main() {
	var user User
	h := `{"Name":"lyd","Age":22}`
	err := json.Unmarshal([]byte(h),&user)
	if err != nil {
		fmt.Println(err)
	}else{
		fmt.Println(user) //{lyd 22}
	}
}

b:структура в JSON

type User struct {
	Name string 
	Age int 
}

func main() {
	user := User{Name:"lyd",Age:22}
	newJson,_ := json.Marshal(&user)
	fmt.Println(string(newJson))  //{"Name":"lyd","Age":22}
}

8. Отражение для получения тега поля

func main() {
	user := User{Name:"lyd",Age:22}
	t := reflect.TypeOf(user)
	for i:=0;i<t.NumField();i++ {
		idx := t.Field(i)
		fmt.Println(idx.Tag)
	}
}
//name
//age

Пара "ключ-значение" тега

type User struct {
	Name string `json:"name"`
	Age int `json:"age"`
}

func main() {
	user := User{Name:"lyd",Age:22}
	t := reflect.TypeOf(user)
	for i:=0;i<t.NumField();i++ {
		idx := t.Field(i)
		fmt.Println(idx.Tag.Get("json"))
	}
}
//name 
//age