结构体标签可以说是 golang 中一个比较有特殊的特性。在讲解 golang 结构体标签之前我们先来看一个结构体标签最常用的场景。有过 web 后端编程的经验的伙伴们应该都会有这样的感受,后端程序处理数据的流程可以抽象为:1、接受前端请求->处理请求->业务数据写入数据库;2、从数据库读取数据->处理业务->向前端返回数据。
在这两个个过程中程序会有两次数据的转换:前端数据(json 数据或者 form 表单)与程序对象或结构体的互转,数据库数据(比如 sql 数据)与程序的对象或结构体的互转。
在 golang 中我们借助 struct tag,这些转换都会特别简单。我们来看一个例子:
package main
import (
"encoding/json"
"net/http"
)
// json:"param-1" 和 json:"param-2 即为结构体标签,其
// 要紧跟在结构体属性后面使用反引号 `` 引起来。
type data struct {
Param1 string `json:"param-1"`
Param2 int `json:"param-2"`
}
func main() {
http.HandleFunc("/getjson", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
reps, err := json.Marshal(data{Param1: "I am a string", Param2: 2})
if err != nil {
panic(err)
}
w.Write([]byte(reps))
})
http.ListenAndServe("0.0.0.0:18080", nil)
}
使用 go run main.go
启动程序后,在使用 curl 命令在检验结果:
# curl -i http://127.0.0.1:18080/getjson
HTTP/1.1 200 OK
Content-Type: application/json
Date: Fri, 30 Sep 2022 07:22:17 GMT
Content-Length: 39
{"param-1":"I am a string","param-2":2}
从上面的例子我们看到借助结构体标签我们能很容易的完成 golang 结构体到 json 数据的转换。除了 json 还有很多其他 golang 库可以完成 golang 结构体到其他数据的转换,如:xml、protocolbuf ;还能用于数据库 orm 相关 beego orm、gorm。
从上面内容我们了解到了使用 golang 结构体标签的方便之处,但是上面我们都是借助各种库来完成数据的转换的。如果这些库不好用,或者我们遇到一套特有的的数据规范第三方库处理不了,我们想自己写一套处理结构体标签的工具,这时候我们就需要掌握 reflect.StructTag
,他是专门用于处理结构体标签的,上面提到的各种库底层都会用到 reflect.StructTag
。
我们来看一个官方的例子:
package main
import (
"fmt"
"reflect"
)
func main() {
type S struct {
F string `species:"gopher" color:"blue"`
}
s := S{}
st := reflect.TypeOf(s)
field := st.Field(0)
fmt.Println(field.Tag.Get("color"), field.Tag.Get("species"))
}
程序运行的输出结果:
blue gopher
reflect.StructTag
非常简单,就包含了两个方法 Get
和 Lookup
,详细的介绍可以参考官方文档,但是要想写出真正有用的工具还需要全面的掌握 golang reflect ,关于 golang reflect 在后续章节我也会逐步介绍到。