Go有什么用途?
在Go语言规范中 ,它提到了标签的简要概述:
字段声明后面可以跟一个可选的字符串字面标记,它成为相应字段声明中所有字段的属性。 标签通过反射界面变得可见,但是被忽略。
// A struct corresponding to the TimeStamp protocol buffer. // The tag strings define the protocol buffer field numbers. struct { microsec uint64 "field 1" serverIP6 uint64 "field 2" process string "field 3" }
这是一个非常简短的解释海事组织,我想知道如果有人可以提供我用这些标签将是什么?
一个字段的标签允许你将元信息附加到可以使用反射获取的字段。 通常用于提供转换信息,如何将结构字段编码为或从其他格式解码(或从数据库中存储/检索),但是您可以使用它来存储您想要的任何元信息,或者用于另一个包或为自己使用。
正如在reflect.StructTag
的文档中所提到的,按照惯例,标记字符串的值是空格分隔的key:"value"
对,例如:
type User struct { Name string `json:"name" xml:"name"` }
key
通常表示随后的"value"
用于的包,例如,由encoding/json
包处理/使用json
密钥。
如果要在"value"
传递多个信息,通常用逗号( ','
)来分隔它,例如
Name string `json:"name,omitempty" xml:"name"`
通常, "value"
的破折号( '-'
)意味着将该字段从进程中排除(例如,在json
情况下,这意味着不对该字段进行编组或解组)。
使用反射访问您的自定义标签的示例
我们可以使用反射( reflect
包)来访问struct字段的标记值。 基本上我们需要获取我们结构的Type
,然后我们可以用Type.Field(i int)
或Type.FieldByName(name string)
查询字段。 这些方法返回描述/表示struct字段的StructField
的值; StructField.Tag
是一个StructField.Tag
类型的值,它描述/表示一个标签值。
以前我们谈到“约定” 。 这个约定意味着如果你遵循它,你可以使用StructTag.Get(key string)
方法来分析标签的值,并返回你指定的key
的"value"
。 这个约定被实现/内置到这个Get()
方法中。 如果你不遵循约定, Get()
将无法解析key:"value"
对,并找到你要找的东西。 这也不是问题,但是你需要实现你自己的解析逻辑。
另外还有StructTag.Lookup()
(在Go 1.7中添加),它与“ Get()
类似,但区分不包含给定键的标签和将空字符串与给定键关联的标签” 。
我们来看一个简单的例子:
type User struct { Name string `mytag:"MyName"` Email string `mytag:"MyEmail"` } u := User{"Bob", "bob@mycompany.com"} t := reflect.TypeOf(u) for _, fieldName := range []string{"Name", "Email"} { field, found := t.FieldByName(fieldName) if !found { continue } fmt.Printf("\nField: User.%s\n", fieldName) fmt.Printf("\tWhole tag value : %q\n", field.Tag) fmt.Printf("\tValue of 'mytag': %q\n", field.Tag.Get("mytag")) }
输出(在Go Playground上试试):
Field: User.Name Whole tag value : "mytag:\"MyName\"" Value of 'mytag': "MyName" Field: User.Email Whole tag value : "mytag:\"MyEmail\"" Value of 'mytag': "MyEmail"
GopherCon 2015有一个关于结构标签的介绍,名为:
结构标签的许多面(幻灯片) (和视频 )
这是一个常用的标签键列表:
-
json
– 由encoding/json
包使用,在json.Marshal()
-
xml
– 由encoding/xml
包使用,详细信息在xml.Marshal()
-
bson
– 由gobson使用 ,详见bson.Marshal()
-
protobuf
– 由github.com/golang/protobuf/proto
,在包文档中有详细说明 -
yaml
– 由gopkg.in/yaml.v2
包使用,详见yaml.Marshal()
-
db
– 由github.com/jmoiron/sqlx
包使用; 也使用github.com/go-gorp/gorp
软件包 -
orm
– 由github.com/astaxie/beego/orm
包使用,在Models – Beego ORM中有详细说明 -
gorm
– 由github.com/jinzhu/gorm
包使用,示例可以在他们的doc: Models中找到 -
valid
– 由github.com/asaskevich/govalidator
包使用,示例可以在项目页面找到 -
datastore
– 由appengine/datastore
(Google App Engine平台,数据存储服务)使用,详见Properties -
schema
– 由github.com/gorilla/schema
用来填充HTML表单值的struct
,在包文档中有详细说明 -
asn
– 由encoding/asn1
包使用,在asn1.Marshal()
和asn1.Unmarshal()
下面是一个非常简单的例子,它使用了encoding/json
包来控制在编码和解码过程中字段的解释方式:
尝试直播: http : //play.golang.org/p/BMeR8p1cKf
package main import ( "fmt" "encoding/json" ) type Person struct { FirstName string `json:"first_name"` LastName string `json:"last_name"` MiddleName string `json:"middle_name,omitempty"` } func main() { json_string := ` { "first_name": "John", "last_name": "Smith" }` person := new(Person) json.Unmarshal([]byte(json_string), person) fmt.Println(person) new_json, _ := json.Marshal(person) fmt.Printf("%s\n", new_json) } // *Output* // &{John Smith } // {"first_name":"John","last_name":"Smith"}
json包可以查看字段的标签,并被告知如何映射json <=> struct字段,还有额外的选项,比如在序列化回json时是否应该忽略空字段。
基本上,任何软件包都可以在字段上使用反射来查看标记值并对这些值进行操作。 反射包中有关于它们的更多信息
http://golang.org/pkg/reflect/#StructTag :
按照惯例,标记字符串是可选空间分隔的键:“值”对的串联。 每个键都是一个非空字符串,由非空格(U + 0020''),引号(U + 0022'“')和冒号(U + 003A':')组成。使用U + 0022'“'字符和Go字符串文字语法。