searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

golang中一种检测字段是否为空的反射方法

2024-05-24 07:16:55
3
0

下面是一段反射的代码

package main

import (
	"fmt"
	"reflect"
)

type Student struct {
	Name string `test_tag:"name"`
	Age  int64  `test_tag:"age1"`
}

func (s Student) Labels() []string {
	ss := []string{}
	t := reflect.TypeOf(s)
	v := reflect.ValueOf(s)
	for i := 0; i < t.NumField(); i++ {
		field := t.Field(i)
		value := v.Field(i)
		tag := field.Tag.Get("test_tag")
		zero := reflect.Zero(reflect.TypeOf(value.Interface()))
		if tag != "" && !reflect.DeepEqual(value.Interface(), zero.Interface()) {
			ss = append(ss, fmt.Sprintf("%s=%v", tag, value))
		}
	}
	return ss
}

func main() {
	s := Student{
		Age:  0,
		Name: "",
	}
	ss := s.Labels()
	fmt.Println(ss)
}
// 上述代码 s:=Studeng{Age:0, Name:""}输出结果为 []
// s := Student{} 输出结果为[]

// 目标状态应为 s:=Student{} 输出 []
// s:=Student{Name:""} 输出 [name=""]
// s:=Student{Age:0} 输出 [age1=0]
// s:=Student{Age:0, Name:""} 输出 [age1=0 name=""]

1、结论

Labels()函数获取Student结构体中非空的字段,并返回tag=value 这种形式的数组,但是上诉代码在恰好s某些字段为对应类型的默认值时无法判断。

2、原因

上诉函数通过reflect.Zero()的函数获取对应结构体字段的默认值,然后比较reflect.DeepEqual()判断是否为空,但是这种方法在恰好遇到对应字段为默认值的时候无法进行正确的判断。

3、解决办法

package main

import (
	"fmt"
	"reflect"
)

type Student struct {
	Name *string `test_tag:"name"`
	Age  *int64  `test_tag:"age1"`
}

func (s Student) Labels() []string {
	ss := []string{}
	t := reflect.TypeOf(s)
	v := reflect.ValueOf(s)
	for i := 0; i < t.NumField(); i++ {
		field := t.Field(i)
		value := v.Field(i)
		tag := field.Tag.Get("test_tag")
		zero := reflect.Zero(reflect.TypeOf(value.Interface()))
		if tag != "" && !reflect.DeepEqual(value.Interface(), zero.Interface()) {
			ss = append(ss, fmt.Sprintf("%s=%v", tag, value.Elem()))
		}
	}
	return ss
}

func main() {
	var age int64 = 0
	var name string = ""
	s := Student{
		Age:  &age,
		Name: &name,
	}
	ss := s.Labels()
	fmt.Println(ss)
}

上述代码中引入 *string *int64 类型,为基础对象引入指针,结构体中存储指针,用指针是否赋值来区别于类型的默认值。上述代码运行结果为 [name= age1=0] 符合预期。

0条评论
0 / 1000
吴溢豪
5文章数
0粉丝数
吴溢豪
5 文章 | 0 粉丝
原创

golang中一种检测字段是否为空的反射方法

2024-05-24 07:16:55
3
0

下面是一段反射的代码

package main

import (
	"fmt"
	"reflect"
)

type Student struct {
	Name string `test_tag:"name"`
	Age  int64  `test_tag:"age1"`
}

func (s Student) Labels() []string {
	ss := []string{}
	t := reflect.TypeOf(s)
	v := reflect.ValueOf(s)
	for i := 0; i < t.NumField(); i++ {
		field := t.Field(i)
		value := v.Field(i)
		tag := field.Tag.Get("test_tag")
		zero := reflect.Zero(reflect.TypeOf(value.Interface()))
		if tag != "" && !reflect.DeepEqual(value.Interface(), zero.Interface()) {
			ss = append(ss, fmt.Sprintf("%s=%v", tag, value))
		}
	}
	return ss
}

func main() {
	s := Student{
		Age:  0,
		Name: "",
	}
	ss := s.Labels()
	fmt.Println(ss)
}
// 上述代码 s:=Studeng{Age:0, Name:""}输出结果为 []
// s := Student{} 输出结果为[]

// 目标状态应为 s:=Student{} 输出 []
// s:=Student{Name:""} 输出 [name=""]
// s:=Student{Age:0} 输出 [age1=0]
// s:=Student{Age:0, Name:""} 输出 [age1=0 name=""]

1、结论

Labels()函数获取Student结构体中非空的字段,并返回tag=value 这种形式的数组,但是上诉代码在恰好s某些字段为对应类型的默认值时无法判断。

2、原因

上诉函数通过reflect.Zero()的函数获取对应结构体字段的默认值,然后比较reflect.DeepEqual()判断是否为空,但是这种方法在恰好遇到对应字段为默认值的时候无法进行正确的判断。

3、解决办法

package main

import (
	"fmt"
	"reflect"
)

type Student struct {
	Name *string `test_tag:"name"`
	Age  *int64  `test_tag:"age1"`
}

func (s Student) Labels() []string {
	ss := []string{}
	t := reflect.TypeOf(s)
	v := reflect.ValueOf(s)
	for i := 0; i < t.NumField(); i++ {
		field := t.Field(i)
		value := v.Field(i)
		tag := field.Tag.Get("test_tag")
		zero := reflect.Zero(reflect.TypeOf(value.Interface()))
		if tag != "" && !reflect.DeepEqual(value.Interface(), zero.Interface()) {
			ss = append(ss, fmt.Sprintf("%s=%v", tag, value.Elem()))
		}
	}
	return ss
}

func main() {
	var age int64 = 0
	var name string = ""
	s := Student{
		Age:  &age,
		Name: &name,
	}
	ss := s.Labels()
	fmt.Println(ss)
}

上述代码中引入 *string *int64 类型,为基础对象引入指针,结构体中存储指针,用指针是否赋值来区别于类型的默认值。上述代码运行结果为 [name= age1=0] 符合预期。

文章来自个人专栏
golang编程
2 文章 | 1 订阅
0条评论
0 / 1000
请输入你的评论
0
0