1 reflect包
reflect包实现了运行时反射,允许程序操作任意类型的对象。典型用法是用静态类型interface{}保存一个值,通过调用TypeOf获取其动态类型信息,该函数返回一个Type类型值。调用ValueOf函数返回一个Value类型值,该值代表运行时的数据。Zero接受一个Type类型参数并返回一个代表该类型零值的Value类型值。
①对基本数据类型进行反射:
package main
import (
"fmt"
"reflect"
)
func reflectNum(arg interface{}) {
fmt.Println("value:", reflect.ValueOf(arg))
fmt.Println("type:", reflect.TypeOf(arg))
}
func main() {
var num float64 = 1.2334
reflectNum(num)
}
控制台输出:
value: 1.2334
type: float64
②对结构体类型进行反射:
package main
import (
"fmt"
"reflect"
)
type User struct {
Id int
Name string
Age int
}
func (u User) Call() {
fmt.Println("User is called ..")
fmt.Printf("%v\n", u)
}
func DoFieldAndMethod(i interface{}) {
//获取input的type
inputType := reflect.TypeOf(i)
fmt.Println("inputType is :", inputType.Name()) //Type类的Name()方法可以直接返回当前类型的名称
//获取input的value
inputValue := reflect.ValueOf(i)
fmt.Println("inputValue is :", inputValue)
//通过Type类和Value类对结构体的字段进行访问
for i := 0; i < inputType.NumField(); i++ { //Type类的NumField()方法返回当前类型属性的个数
field := inputType.Field(i) //Type类的Field(i int)方法返回当前类的第i个字段
value := inputValue.Field(i).Interface() //通过Value类的Field()拿到当前类的第i个字段,再通过Interface()返回v当前持有的值(表示为/保管在interface{}类型)
fmt.Printf("%s : %v = %v\n", field.Name, field.Type, value)
}
//通过type获取里面的方法
for i := 0; i < inputType.NumMethod(); i++ { //Type类的NumMethod()方法返回当前类型方法的个数
m := inputType.Method(i)
fmt.Printf("%s : %v\n", m.Name, m.Type)
}
}
func main() {
user := User{1, "liam", 23}
//fmt.Println(reflect.ValueOf(user).Field(1).Interface())
DoFieldAndMethod(user)
}
控制台输出:
inputType is : User
inputValue is : {1 liam 23}
Id : int = 1
Name : string = liam
Age : int = 23
Call : func(main.User)
2 反射解析结构体标签Tag
可以在结构体字段后用“ `` ”来对字段添加说明标签:
type resume struct {
Name string `info:"name" doc:"我的名字"`
Gender rune `info:"gender"`
}
可以通过反射来访问结构体字段的Tag:
package main
import (
"fmt"
"reflect"
)
type resume struct {
Name string `info:"name" doc:"我的名字"`
Gender rune `info:"gender"`
}
func findTag(str interface{}) {
t := reflect.TypeOf(str).Elem()
for i := 0; i < t.NumField(); i++ {
tagInfo := t.Field(i).Tag.Get("info")
tagDoc := t.Field(i).Tag.Get("doc")
fmt.Println("info:", tagInfo, "doc:", tagDoc)
}
}
func main() {
var re resume
findTag(&re)
}
控制台输出:
info: name doc: 我的名字
info: gender doc:
2.1 结构体标签在json中的应用
可以通过encoding/json
包来将结构体和json格式相互转换:
package main
import (
"encoding/json"
"fmt"
)
type Movie struct {
Title string `json:"title"`
Year int `json:"year"`
Price int `json:"rmb"`
Actors []string `json:"actors"`
}
func main() {
movie := Movie{
Title: "CatchMeIfYouCan",
Year: 2002,
Price: 20,
Actors: []string{"Leonardo", "TomHanks"},
}
//编码过程:结构体--->json
jsonStr, err := json.Marshal(movie)
if err != nil {
fmt.Println("json marshal err:", err)
return
}
fmt.Printf("%s\n", jsonStr)
//解码过程:json--->结构体
myMovie := Movie{}
err = json.Unmarshal(jsonStr, &myMovie)
if err != nil {
fmt.Println("json unmarshal err:", err)
return
}
fmt.Printf("%v\n", myMovie)
}
控制台输出:
{"title":"CatchMeIfYouCan","year":2002,"rmb":20,"actors":["Leonardo","TomHanks"]}
{CatchMeIfYouCan 2002 20 [Leonardo TomHanks]}
标签:reflect,反射,fmt,golang,json,func,main,Type
From: https://www.cnblogs.com/SpriteLee/p/16610845.html