golang变量 = type + value
golang里,一个变量,只要确定了它的类型和值,就可以确定该变量
也因此,两个nil是无法比较的
package main
import "fmt"
func main() {
fmt.Println(nil == nil) // invalid operation: nil == nil (operator == not defined on nil)
}
两个nil都是untyped的无类型值,无法比较
反射
在程序运行过程中获取变量的类型信息、字段名称、结构体信息和值等
反射信息由reflect.Type和reflect.Value两部分组成,分别由reflect.TypeOf
和 reflect.ValueOf
两个函数来获取
涉及与变量值有关的操作,使用reflect.Value相关的方法;别的操作,使用reflect.Type的相关方法
参考
http://c.biancheng.net/view/4407.html
https://draveness.me/golang/docs/part2-foundation/ch04-basic/golang-reflect/
https://eddycjy.com/posts/go/reflect/
反射的应用 struct to map[string]interface{} by reflect
一个结构体可以拥有多种类型的成员变量,可以映射成map[string]interface{}
package main
import (
"reflect"
"fmt"
)
type student struct {
Name string `json:"stu_name"`
Age int
Sex string
}
func main() {
s := student{
Age: 10,
}
m := Struct2Map(s)
fmt.Printf("%+v\n", m)
}
func Struct2Map(obj interface{}) map[string]interface{} {
t := reflect.TypeOf(obj) // 获取obj的反射类型
v := reflect.ValueOf(obj) // 获取obj的反射值
var data = make(map[string]interface{})
for i := 0; i < t.NumField(); i++ {
// 存在tag,则使用tag作为key
var key string
tag := t.Field(i).Tag.Get("json")
if tag != "" {
key = tag
} else {
key = t.Field(i).Name
}
data[key] = v.Field(i).Interface()
}
return data
}
>>>
map[Age:10 Sex: stu_name:]
反射的应用 struct assign by reflect
package main
import (
"fmt"
"reflect"
)
type A struct {
Name string
Gender string
Age int
}
type B struct {
Name string
Gender string
}
// StructAssign sourceStruct将值赋予targetStruct同名同类型的字段
func StructAssign(targetStructPtr interface{}, sourceStructPtr interface{}) error {
// 参数校验
st := reflect.TypeOf(sourceStructPtr)
if st.Kind() != reflect.Ptr {
return fmt.Errorf("source must be a struct pointer")
}
tt := reflect.TypeOf(targetStructPtr)
if tt.Kind() != reflect.Ptr {
return fmt.Errorf("target must be a struct pointer")
}
//获取reflect.Type类型
tVal := reflect.ValueOf(targetStructPtr).Elem()
sVal := reflect.ValueOf(sourceStructPtr).Elem()
// 遍历目标struct全部字段
for i := 0; i < tVal.NumField(); i++ {
// 在源结构体中查询有数据结构体中相同属性和类型的字段,有则修改其值
// name := sTypeOfT.Field(i).Name
f := tVal.Type().Field(i)
name := f.Name
targetFiled := sVal.FieldByName(name)
if targetFiled.IsValid() && f.Type == targetFiled.Type() {
tVal.Field(i).Set(reflect.ValueOf(sVal.FieldByName(name).Interface()))
}
}
return nil
}
func main() {
as := A{}
bs := B{Name: "wfy", Gender: "男"}
fmt.Println(as)
err := StructAssign(&as, &bs)
fmt.Println(err)
fmt.Println(as)
}
// see https://go.dev/play/p/9BdE9Rj_Uwx
网友评论