Go语言实现结构体初始化设置默认值

作者: 乘风御上者 分类: GoLang 发布时间: 2022-06-01 14:17

在Go语言中结构体原生语法是不支持设置默认值的,这就在很多场景中需要增加额外的步骤,去设置一些默认值。

自从 Go 1.18支持泛型后,再通过反射功能即可实现为结构体设置默认值。

原理也非常简单,只要将结构体的标签中设置一个Key,即可通过Key的值赋予对象的指定字段。

package main

import (
	"fmt"
	"reflect"
	"strconv"
)

type Person struct {
	Name string `df:"无名氏"`
	Age  int    `df:"18"`
}

func main() {
  // 实例化类并指定标签
	p := NewClass(Person{}, "df")
  // 结果:{无名氏 18}
	fmt.Println(p)
}

// 实例化结构体
// 目前只能实现基本数据类型
func NewClass[T any](cls T, dfKey string) T {

	rt := reflect.ValueOf(&cls).Elem()
	vt := rt.Type()

	for i := 0; i < rt.NumField(); i++ {

		f := rt.Field(i)
		tag, ok := vt.Field(i).Tag.Lookup(dfKey)
		if ok {
			switch f.Kind() {

			case reflect.Bool:
				i, _ := strconv.ParseBool(tag)
				f.SetBool(i)

			case reflect.String:
				f.SetString(tag)

			case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
				i, _ := strconv.ParseInt(tag, 10, 64)
				f.SetInt(i)

			case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
				i, _ := strconv.ParseUint(tag, 10, 64)
				f.SetUint(i)

			case reflect.Float32, reflect.Float64:
				i, _ := strconv.ParseFloat(tag, 64)
				f.SetFloat(i)

      // 更多数据类型支持需要自己定义规则
			}
		}
	}

	return cls
}

如果觉得我的文章对您有用,请随意赞赏。您的支持将鼓励我继续创作!

发表回复