Go 判断传入的是否是一个结构体类型
用 reflect 包,判断 Kind() 是否为 reflect.Struct
go
func isStruct(v interface{}) bool {
if v == nil {
return false
}
return reflect.TypeOf(v).Kind() == reflect.Struct
}
获取字段名,字段类型,字段标签
go
package main
import (
"fmt"
"reflect"
)
// 学生结构体
type Student struct {
Name string `json:"name" form:"userName"`
Age int `json:"age"`
Score int `json:"score"`
}
// 获取结构体的信息
func (s Student) GetInfo() string {
var str = fmt.Sprintf("姓名: %v, 年龄: %v, 成绩: %v", s.Name, s.Age, s.Score)
return str
}
// 设置结构体的信息,这个参数应该是指针类型的【重要】
func (s *Student) SetInfo(name string, age int, score int) {
s.Name = name
s.Age = age
s.Score = score
}
func (s Student) Print() {
fmt.Println("这是一个打印的方法")
}
// 打印字段
func PrintStructField(s interface{}) {
// 通过反射来获取变量的类型;t的值是: *main.Student; * 表示这是一个指针类型
// 通过反射来获取变量的类型
t := reflect.TypeOf(s)
// 【关键修改1】如果是指针,先解引用拿到实际的结构体类型
if t.Kind() == reflect.Ptr {
t = t.Elem()
}
// 【关键修改2】统一判断解引用后的类型是否是结构体
if t.Kind() != reflect.Struct {
fmt.Println("不是结构体类型")
return
}
// 通过类型变量里面的Field可以获取结构体的字段
filed := t.Field(0)
fmt.Println(filed)
fmt.Printf("获取字段名: %v\n", filed.Name)
fmt.Printf("获取字段类型: %v\n", filed.Type)
fmt.Printf("获取字段标签: %v\n", filed.Tag.Get("json"))
fmt.Printf("获取字段标签: %v\n", filed.Tag.Get("form"))
}
// 入口函数
func main() {
// 实例化这个结构体
stu1 := Student{
Name: "张三",
Age: 18,
Score: 90,
}
// 传入的是一个指针,
PrintStructField(&stu1)
}
{Name string json:"name" form:"userName" 0 0 false}
获取字段名: Name
获取字段类型: string
获取字段标签: name
获取字段标签: userName
通过 FieldByName 获取结构体中的字段
go
package main
import (
"fmt"
"reflect"
)
// 学生结构体
type Student struct {
Name string `json:"name" form:"userName"`
Age int `json:"age"`
Score int `json:"score"`
}
// 获取结构体的信息
func (s Student) GetInfo() string {
var str = fmt.Sprintf("姓名: %v, 年龄: %v, 成绩: %v", s.Name, s.Age, s.Score)
return str
}
// 设置结构体的信息,这个参数应该是指针类型的【重要】
func (s *Student) SetInfo(name string, age int, score int) {
s.Name = name
s.Age = age
s.Score = score
}
func (s Student) Print() {
fmt.Println("这是一个打印的方法")
}
// 打印字段
func PrintStructField(s interface{}) {
// 通过反射来获取变量的类型;t的值是: *main.Student; * 表示这是一个指针类型
// 通过反射来获取变量的类型
t := reflect.TypeOf(s)
// 【关键修改1】如果是指针,先解引用拿到实际的结构体类型
if t.Kind() == reflect.Ptr {
t = t.Elem()
}
// 【关键修改2】统一判断解引用后的类型是否是结构体
if t.Kind() != reflect.Struct {
fmt.Println("不是结构体类型")
return
}
// 通过类型变量里面的Field可以获取结构体的字段
filed, ok := t.FieldByName("Name")
if ok {
fmt.Printf("获取字段名: %v\n", filed.Name)
fmt.Printf("获取字段类型: %v\n", filed.Type)
fmt.Printf("获取字段标签: %v\n", filed.Tag.Get("json"))
fmt.Printf("获取字段标签: %v\n", filed.Tag.Get("form"))
}
}
// 入口函数
func main() {
// 实例化这个结构体
stu1 := Student{
Name: "张三",
Age: 18,
Score: 90,
}
// 传入的是一个指针,
PrintStructField(&stu1)
}
获取字段名: Name
获取字段类型: string
获取字段标签: name
获取字段标签: userName
获取结构体有多少个字段
go
// 打印字段
func PrintStructField(s interface{}) {
// 通过反射来获取变量的类型;t的值是: *main.Student; * 表示这是一个指针类型
// 通过反射来获取变量的类型
t := reflect.TypeOf(s)
// 【关键修改1】如果是指针,先解引用拿到实际的结构体类型
if t.Kind() == reflect.Ptr {
t = t.Elem()
}
// 【关键修改2】统一判断解引用后的类型是否是结构体
if t.Kind() != reflect.Struct {
fmt.Println("不是结构体类型")
return
}
// 获取结构体有多少个字段
fmt.Printf("结构体有 %v 个字段\n", t.NumField())
}
结构体有 3 个字段
ps:注意值变量和类型变量哈
获取结构体属性对应的值
scss
func PrintStructField(s interface{}) {
v := reflect.ValueOf(s)
fmt.Printf("获取结构体属性对应的值: %v\n", v.FieldByName("Name"))
}
for循环获取属性名和属性的类型
go
// 打印字段
func PrintStructField(s interface{}) {
t := reflect.TypeOf(s)
var fieldCount = t.NumField()
for i := 0; i < fieldCount; i++ {
fmt.Printf("字段名: %v, 字段类型: %v\n", t.Field(i).Name, t.Field(i).Type)
}
}
字段名: Name, 字段类型: string
字段名: Age, 字段类型: int
字段名: Score, 字段类型: int
获取结构体中的方法
go
package main
import (
"fmt"
"reflect"
)
// 学生结构体
type Student struct {
Name string `json:"name" form:"userName"`
Age int `json:"age"`
Score int `json:"score"`
}
// 获取结构体的信息
func (s Student) GetInfo() string {
var str = fmt.Sprintf("姓名: %v, 年龄: %v, 成绩: %v", s.Name, s.Age, s.Score)
return str
}
// 设置结构体的信息,这个参数应该是指针类型的【重要】
func (s *Student) SetInfo(name string, age int, score int) {
s.Name = name
s.Age = age
s.Score = score
}
func (s Student) Print() {
fmt.Println("这是一个打印的方法")
}
// 打印字段
func PrintStructField(s interface{}) {
// 通过反射来获取变量的类型;t的值是: *main.Student; * 表示这是一个指针类型
// 通过反射来获取变量的类型
t := reflect.TypeOf(s)
// 获取结构体中的方法
// 和结构体方法的顺序没有关系,和结构体方法的ASCII有关系
method0 := t.Method(0)
fmt.Println(method0.Name) // GetInfo
fmt.Println(method0.Type) // func(main.Student) string
}
// 入口函数
func main() {
// 实例化这个结构体
stu1 := Student{
Name: "张三",
Age: 18,
Score: 90,
}
// 传入的是一个指针,
PrintStructField(stu1)
}
GetInfo func(main.Student) string
获取结构体中的方法名称和方法
go
package main
import (
"fmt"
"reflect"
)
// 学生结构体
type Student struct {
Name string `json:"name" form:"userName"`
Age int `json:"age"`
Score int `json:"score"`
}
// 获取结构体的信息
func (s Student) GetInfo() string {
var str = fmt.Sprintf("姓名: %v, 年龄: %v, 成绩: %v", s.Name, s.Age, s.Score)
return str
}
// 设置结构体的信息,这个参数应该是指针类型的【重要】
func (s *Student) SetInfo(name string, age int, score int) {
s.Name = name
s.Age = age
s.Score = score
}
func (s Student) Print() {
fmt.Println("这是一个打印的方法")
}
// 打印字段
func PrintStructField(s interface{}) {
// 通过反射来获取变量的类型;t的值是: *main.Student; * 表示这是一个指针类型
// 通过反射来获取变量的类型
t := reflect.TypeOf(s)
// 获取结构体中的方法
method, ok := t.MethodByName("Print")
if ok {
// 输出:Print
fmt.Println(method.Name)
// 输出: func(main.Student)
fmt.Println(method.Type)
}
}
// 入口函数
func main() {
// 实例化这个结构体
stu1 := Student{
Name: "张三",
Age: 18,
Score: 90,
}
// 传入的是一个指针,
PrintStructField(stu1)
}
Print func(main.Student)
调用方法
go
package main
import (
"fmt"
"reflect"
)
// 学生结构体
type Student struct {
Name string `json:"name" form:"userName"`
Age int `json:"age"`
Score int `json:"score"`
}
// 获取结构体的信息
func (s Student) GetInfo() string {
var str = fmt.Sprintf("姓名: %v, 年龄: %v, 成绩: %v", s.Name, s.Age, s.Score)
return str
}
// 设置结构体的信息,这个参数应该是指针类型的【重要】
func (s *Student) SetInfo(name string, age int, score int) {
s.Name = name
s.Age = age
s.Score = score
}
func (s Student) Print() {
fmt.Println("这是一个打印的方法")
}
// 打印字段
func PrintStructField(s interface{}) {
// 通过反射来获取变量的类型;t的值是: *main.Student; * 表示这是一个指针类型
// 通过反射来获取变量的类型
v := reflect.ValueOf(s)
// 调用方法, 第一个参数是方法的索引, 第二个参数是方法的参数
// 如果方法没有 参数,需要在Call方法中写上nil,否则会报错
v.Method(1).Call(nil)
// 通过另外一种方式来进行调用方法
v.MethodByName("Print").Call(nil)
// 调用方法,接收方法返回来的值
info := v.MethodByName("GetInfo").Call(nil)
// [姓名: 张三, 年龄: 18, 成绩: 90]
fmt.Println(info)
}
// 入口函数
func main() {
// 实例化这个结构体
stu1 := Student{
Name: "张三",
Age: 18,
Score: 90,
}
// 传入的是一个指针,
PrintStructField(stu1)
}
这是一个打印的方法
调用方法修改结构体中的数据
go
package main
import (
"fmt"
"reflect"
)
// 学生结构体
type Student struct {
Name string `json:"name" form:"userName"`
Age int `json:"age"`
Score int `json:"score"`
}
// 获取结构体的信息
func (s Student) GetInfo() string {
var str = fmt.Sprintf("姓名: %v, 年龄: %v, 成绩: %v", s.Name, s.Age, s.Score)
return str
}
// 设置结构体的信息,这个参数应该是指针类型的【重要】
func (s *Student) SetInfo(name string, age int, score int) {
s.Name = name
s.Age = age
s.Score = score
}
func (s Student) Print() {
fmt.Println("这是一个打印的方法")
}
// 打印字段
func PrintStructField(s interface{}) {
// 通过反射来获取变量的类型;t的值是: *main.Student; * 表示这是一个指针类型
// 通过反射来获取变量的类型
v := reflect.ValueOf(s)
// 调用方法并且传入参数
var params []reflect.Value // 定义一个切片,类型是 reflect.Value
params = append(params, reflect.ValueOf("WangWen"))
params = append(params, reflect.ValueOf(18))
params = append(params, reflect.ValueOf(90))
// call参数类型是:[]reflect.Value;因此前面我们需要声明一下参数的类型
// 设置结构体的信息
v.MethodByName("SetInfo").Call(params)
// 调用方法,接收方法返回来的值
info := v.MethodByName("GetInfo").Call(nil)
fmt.Printf("获取到的信息是:%v", info)
}
// 入口函数
func main() {
// 实例化这个结构体
stu1 := Student{
Name: "张三",
Age: 18,
Score: 90,
}
// 传入的是一个指针,
PrintStructField(&stu1)
}
获取到的信息是:姓名: WangWen, 年龄: 18, 成绩: 90
获取方法的数量
go
// 打印字段
func PrintStructField(s interface{}) {
// 通过反射来获取变量的类型;t的值是: *main.Student; * 表示这是一个指针类型
// 通过反射来获取变量的类型
v := reflect.ValueOf(s)
// 获取方法的数量(格式)
methodNum := v.NumMethod()
fmt.Printf("方法的数量是:%v", methodNum)
}
通过反射修改结构体中的值
go
package main
import (
"fmt"
"reflect"
)
// 学生结构体
type Student struct {
Name string `json:"name" form:"userName"`
Age int `json:"age"`
Score int `json:"score"`
}
// 获取结构体的信息
func (s Student) GetInfo() string {
var str = fmt.Sprintf("姓名: %v, 年龄: %v, 成绩: %v", s.Name, s.Age, s.Score)
return str
}
// 设置结构体的信息,这个参数应该是指针类型的【重要】
func (s *Student) SetInfo(name string, age int, score int) {
s.Name = name
s.Age = age
s.Score = score
}
func (s Student) Print() {
fmt.Println("这是一个打印的方法")
}
// 打印字段
func PrintStructField(s interface{}) {
t := reflect.TypeOf(s)
v := reflect.ValueOf(s)
if t.Kind() != reflect.Ptr {
fmt.Println("传入的参数不是指针类型")
return
} else if t.Elem().Kind() != reflect.Struct {
fmt.Println("传入的参数不是结构体类型")
return
}
// 修改结构体属性的值(也就是修改value的值)
name := v.Elem().FieldByName("Name")
name.SetString("大李四")
age := v.Elem().FieldByName("Age")
age.SetInt(20)
}
// 入口函数
func main() {
// 实例化这个结构体
stu1 := Student{
Name: "张三",
Age: 18,
Score: 90,
}
// 传入的是一个指针,
PrintStructField(&stu1)
fmt.Printf("%v\n", stu1)
}