Golang 结构体标签对于Go本身来说就是注释,但是这个字符串可以通过reflect API访问到,因此不同的包可能会赋予自己的含义。
具体你看看encoding/xml和encoding/json的文档。
例如:

  1. type Config struct {
  2. Log string `myConf:"base:log"` //myConf为自定义的结构体
  3. }

在Go语言当中,好多功能都使用了结构体标签。主要应用在encoding/json和encoding/xml之中。那么我们先用Json的使用做一个例子。首先创建一个结构体。

  1. type User struct {
  2. Id int `json:"id"`
  3. Name string `json:"name"`
  4. Bio string `json:"about,omitempty"`
  5. Active bool `json:"active"`
  6. Admin bool `json:"-"`
  7. CreatedAt time.Time `json:"created_at"`
  8. }

对于结构体的标签就是紧跟成员定义后,类型后面的那串字符串,就是标签。其中出现的这个是Golang为了保持源字符串的意思。这个结构体标签,在编码后,Json中的Key值就会被响应的tag个中json后面的名称代替,在此使用的是Go语言的包反射机理获取标签再填充为Json,具体我们下文再说。在没有使用结构体表情的情况下,我们使用json.Marshal进行处理后输出的是这样的:

  1. {
  2. "Id": 1,
  3. "Name": "John Doe",
  4. "Bio": "Some Text",
  5. "Active": true,
  6. "Admin": false,
  7. "CreatedAt": "2016-07-16T15:32:17.957714799Z"
  8. }

和结构体所定义的结构成员的名称是一致的,当我们使用结构体标签后:

  1. {
  2. "id": 1,
  3. "name": "John Doe",
  4. "about": "Some Text",
  5. "active": true,
  6. "created_at": "2016-07-16T15:32:17.957714799Z"
  7. }

可以很清晰的看到,结构体标签上的json后面的那段字符串,成为了Json中的Key值。在此我们查看Go语言中的Json和XML包源码,是很清晰的可以看到这一点的。对于自己开发获取,我们可以使用编程中的包反射进行获取结构体的标签名

  1. package main
  2. import (
  3. "fmt"
  4. "reflect"
  5. )
  6. // Name of the struct tag used in examples
  7. const tagName = "validate"
  8. type User struct {
  9. Id int `validate:"-"`
  10. Name string `validate:"presence,min=2,max=32"`
  11. Email string `validate:"email,required"`
  12. }
  13. func main() {
  14. user := User{
  15. Id: 1,
  16. Name: "John Doe",
  17. Email: "john@example",
  18. }
  19. // TypeOf returns the reflection Type that represents the dynamic type of variable.
  20. // If variable is a nil interface value, TypeOf returns nil.
  21. t := reflect.TypeOf(user)
  22. // Get the type and kind of our user variable
  23. fmt.Println("Type:", t.Name())
  24. fmt.Println("Kind:", t.Kind())
  25. // Iterate over all available fields and read the tag value
  26. for i := 0; i < t.NumField(); i++ {
  27. // Get the field, returns https://golang.org/pkg/reflect/#StructField
  28. field := t.Field(i)
  29. // Get the field tag value
  30. tag := field.Tag.Get(tagName)
  31. fmt.Printf("%d. %v (%v), tag: '%v'\n", i+1, field.Name, field.Type.Name(), tag)
  32. }
  33. }

其中首先导入了reflect这个包,然后通过reflect中的TypeOf,将user结构体变成动态变量。然后遍历结构体程序,通过.Tag.Get方法获取结构体的每一个成员的标签,然后去做我们想做的事情~

  1. Type: User
  2. Kind: struct
  3. 1. Id (int), tag: '-'
  4. 2. Name (string), tag: 'presence,min=2,max=32'
  5. 3. Email (string), tag: 'email,required'

看完下面的例子你就明白啦,这个例子,解析时可以把json中name解析成struct中的Name(大小写不一样),把emailAddress解析成Email(名字都不一样):

  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. )
  6. // Name of the struct tag used in examples
  7. type User struct {
  8. Id int `json:"id"`
  9. Name string `json:"name"`
  10. Email string `json:"emailAddress"`
  11. }
  12. func main() {
  13. u := &User{}
  14. // str := []byte(`{"name":"lee","id":5266, "mail":"test@163.com"}`) //这个不能导出mail,因为mail不是`Email`, 也不是`emailAddress`,所以不能导出
  15. str := []byte(`{"name":"lee","id":5266, "emailAddress":"test@163.com"}`)
  16. if err := json.Unmarshal(str, u); err != nil {
  17. return
  18. }
  19. fmt.Println(u)
  20. }

分类: web

标签:   golang