Go中标签的用途是什么?

Python014

Go中标签的用途是什么?,第1张

字段标签允许您将元信息附加到可以使用反射获取的字段上。通常,它用于提供有关如何将结构域编码为另一种格式(或从另一种格式存储(或从数据库中检索))的转换信息,但是您可以使用它存储想要存储的任何元信息,这些元信息既可以用于另一种包装或供您自己使用。

如的文档所述reflect.StructTag,按照惯例,标记字符串的值是用空格分隔的key:"value"成对列表,如:

type User struct {

Name string `json:"name" xml:"name"`

}

的key通常表示包,随后的"value"是,如json密钥被处理/使用的encoding/json包。

如果要在中传递多个信息"value",通常通过用逗号(',')隔开来指定它,如

Name string `json:"name,omitempty" xml:"name"`

通常用破折号('-')"value"表示将字段从过程中排除(如,在这种情况下,json表示不封送或取消封送该字段)。

使用反射访问自定义标签的示例

我们可以使用反射(reflect包)来访问结构字段的标记值。基本上,我们需要获取Type结构的,然后可以使用Type.Field(i

int)或查询字段Type.FieldByName(name

string)。这些方法返回的值StructField描述/表示一个struct字段;并且StructField.Tag是StructTag描述/表示标记值的类型值。

以前我们谈论过 “惯例” 。该公约的手段,如果你遵循它,你可以使用StructTag.Get(key

string)它解析变量的值,并返回该方法"value"的key指定。该公约实施/内置到这个Get()方法。如果不遵守约定,Get()将无法解析key:"value"对并找到您要查找的内容。这也不是问题,但是随后您需要实现自己的解析逻辑。

还有StructTag.Lookup()(在Go1.7中添加了),它 “类似于,Get()但是将不包含给定键的标签与将空字符串与给定键相关联的标签区分开”。因此,看一个简单的示例:

type User struct {

Name  string `mytag:"MyName"`

Email string `mytag:"MyEmail"`}

u := User{"Bob", "[email protected]"}

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上有一个关于struct标签的演示,名为:结构标签的许多面孔(幻灯片)

(和视频)以下是常用标签键的列表:

json-由encoding/json包装使用,详细说明json.Marshal()

xml-由encoding/xml包装使用,详细说明xml.Marshal()

bson-由gobson使用,详细说明bson.Marshal()

protobuf-由github.com/golang/protobuf/proto,在软件包doc中有详细说明

yaml-由gopkg.in/yaml.v2包装使用,详细说明yaml.Marshal()

db-由github.com/jmoiron/sqlx包装使用;也被github.com/go-gorp/gorp包装使用

orm-由github.com/astaxie/beego/orm包装使用,在“ 型号– Beego ORM”中有详细说明

gorm-由github.com/jinzhu/gorm软件包使用,示例可在其文档中找到:模型

valid-由github.com/asaskevich/govalidator软件包使用,示例可以在项目页面中找到

datastore-由appengine/datastore(Google App Engine平台,数据存储区服务)使用,在“ 属性”中有详细说明

schema-用于通过HTML表单值github.com/gorilla/schema填充(struct包文档中有详细说明)

asn-由encoding/asn1包装使用,详细说明在asn1.Marshal()和asn1.Unmarshal()

csv-由github.com/gocarina/gocsv包装使用

现代应用支持多平台运行是一件稀松平常的事情,在 Go 语言里面,为了支持应用的多平台部署,给用户提供了方便的配置方式来轻松构建针对不同操作系统和平台的运行文件。

Go 的构建约束,即构建标签,是以 // go:build 为开始的行注释,如果是 1.16 或之前的版本,格式是 // +build 。跟此变更相关的 issue 可以参考 25348 。

构建标签必须出现在 package 子句之前。为了区分构建标签和包文档的描述注释,构建标签后面应该有一个空行。

构建标签由||, &&, !运算符以及括号来组合表达。运算符与 Go 中的含义相同。

例如,以下构建标签在满足 linux 和 386 约束,或者满足 darwin 而 cgo 不满足时构建文件:

//go:build (linux &&386) || (darwin &&!cgo)

又如:仅在使用 cgo 时,且仅在 Linux 和 OS X 上构建文件: //go:build cgo &&(linux || darwin)

注意:1.17 及以后的表达格式里,一个文件有多个 //go:build 行是错误的。

在 1.16 及以前的版本,多行构建标签是允许的,并且组合方式是通过空格和逗号等来区分,空格符表示 OR,逗号表示 AND,感叹号表示 NOT。而多行之间则表示 OR。gofmt 命令将在遇到旧语法时添加等效的 //go:build 约束。如下是示例:

如果文件名在去除扩展名和可能的 _test 后缀后匹配以下任何模式, (例如:source_windows_amd64.go)其中 GOOS 和 GOARCH 分别代表任何已知的操作系统和体系结构值,那么认为该文件除了文件中的任何显式约束之外,具有这些术语的所表达的隐式构建标签。

除了官方提供的针对不同平台的内置标签,用户也可以使用自定义标签,例如 //go:build prod , 只需要在执行 go build 时显式带上标签名 go build --tags=prod 。

想要使文件构建时被忽略,可以使用: //go:build ignore ,其他任何没有被用来定义为标签的词也可以,但"ignore"是约定俗成的。)。Go 语言目前支持的系统和架构可以参考 官方文档 。

目录

一、结构体详解

1. 结构体定义

2. 实例化结构体的7种方法

二、结构体方法

1. 结构体的方法定义

2. 结构体内自定义方法的引用

3. 任意类型添加方法

三、嵌套、继承

1. 匿名结构体

2. 结构体中可以定义任意类型的字段

3. 结构体嵌套结构体

4. 结构体嵌套匿名结构体

5. 结构体嵌套多个匿名结构体

6. 结构体继承

四、结构体和JSON相互转换

1. 结构体转化成json

2. json转化成结构体

3. 结构体标签 tag

4. 嵌套结构体和json的序列化反序列化

Golang 中没有“类”的概念,Golang 中的结构体和其他语言中的类有点相似。和其他面向对 象语言中的类相比,Golang 中的结构体具有更高的扩展性和灵活性。

Golang 中的基础数据类型可以表示一些事物的基本属性,但是当我们想表达一个事物的全 部或部分属性时,这时候再用单一的基本数据类型就无法满足需求了,Golang 提供了一种 自定义数据类型,可以封装多个基本数据类型,这种数据类型叫结构体,英文名称 struct。 也就是我们可以通过 struct 来定义自己的类型了。

使用 type 和 struct 关键字来定义结构体,具体代码格式如下:

type 类型名 struct {

字段名 字段类型

字段名 字段类型 …

}

其中:

• 类型名:表示自定义结构体的名称,在同一个包内不能重复。

• 字段名:表示结构体字段名。结构体中的字段名必须唯一。

• 字段类型:表示结构体字段的具体类型。

在 go 语言中,没有类的概念但是可以给类型(结构体,自定义类型)定义方法。所谓方法 就是定义了接收者的函数。接收者的概念就类似于其他语言中的 this 或者 self。

方法的定义格式如下:

func (接收者变量 接收者类型) 方法名(参数列表) (返回参数) {

函数体

}

注意:想改变结构体内的值,必须先变成指针。

在 Go 语言中,接收者的类型可以是任何类型,不仅仅是结构体,任何类型都可以拥有方法。 举个例子,我们基于内置的 int 类型使用 type 关键字可以定义新的自定义类型,然后为我们 的自定义类型添加方法。

注意:匿名结构体中不允许出现多个重复的类型

注意:如果结构体里面有私有属性也就是小写定义的字段,则不会被json使用