golang反射自定义tag
golang reflect包实现了反射。动态的获得程序运行时对象的结构和信息。
reflect 包中提供了两个基础的关于反射的函数来获取上述的接口和结构体:
func TypeOf(i interface{}) Type func ValueOf(i interface{}) Value
大体上可以这样理解,TypeOf获取对象的类型信息,ValueOf获取对象中存储的值。
golang tag
golang中可以为结构体的字段添加tag。golang本身的encoding/json包解析json使用了tag,一些开源的orm框架如gorm,也使用了tag。tag可以方便的为结构体的字段添加一些信息,用reflect可以读取到,加以利用。
这是一个用tag标记列名以实现结构体自动生成xlsx的例子:
type Employee struct{ ID int `xlsx:”工号”` Name string `xlsx:”姓名”` Email string `xlsx:”邮箱”` } func Outputxlsx(es []*Employee) ([]byte, error) { xt := reflect.TypeOf(es[0]) xv := reflect.ValueOf(es[0]) rows := [][]interface{}{} headers := []interface{}{} for i := 0; i < xt.Elem().NumField(); i++ { head, ok := xt.Elem().Field(i).Tag.Lookup("xlsx") if ok { headers = append(headers, head) } } for _, e := range es { cells := []interface{}{} xv := reflect.ValueOf(e) for i := 0; i < xv.Elem().NumField(); i++ { _, ok := xt.Elem().Field(i).Tag.Lookup("xlsx") if ok { cells = append(cells, xv.Elem().Field(i).Interface()) } } rows = append(rows, cells) } file := xlsx.NewFile() sheet, _ := file.AddSheet("sheet1") row := sheet.AddRow() for _, header := range headers { row.AddCell().Value = fmt.Sprintf("%v", header) } for _, v := range rows { row := sheet.AddRow() for _, vv := range v { row.AddCell().Value = fmt.Sprintf("%v", vv) } } var buffer bytes.Buffer if err := file.Write(&buffer); err != nil { return nil, err } return buffer.Bytes(), nil }