Go языковые боевые заметки (двадцать четыре) | Go рефлексия(рекомендуется к просмотру)
Боевые заметки о языке Go (25) | Go Struct Tag(рекомендуется к просмотру)
Принцип реализации пакета отражения на языке 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