教程集 www.jiaochengji.com
教程集 >  Golang编程  >  golang教程  >  正文 golang 结构体标签_如何在Go中使用结构标签

golang 结构体标签_如何在Go中使用结构标签

发布时间:2022-02-16   编辑:jiaochengji.com
教程集为您提供golang 结构体标签,如何在Go中使用结构标签等资源,欢迎您收藏本站,我们将为您提供最新的golang 结构体标签,如何在Go中使用结构标签资源

golang 结构体标签

<h3 id="introduction"> 介绍 <span style="font-weight: bold;">(</span>Introduction<span style="font-weight: bold;">)</span></h3>

Structures, or structs, are used to collect multiple pieces of information together in one unit. These collections of information are used to describe higher-level concepts, such as an <code>Address</code> composed of a <code>Street</code>, <code>City</code>, <code>State</code>, and <code>PostalCode</code>. When you read this information from systems such as databases, or APIs, you can use struct tags to control how this information is assigned to the fields of a struct. Struct tags are small pieces of metadata attached to fields of a struct that provide instructions to other Go code that works with the struct.

结构或结构用于在一个单元中收集多条信息。 这些信息收集用于描述更高级别的概念,例如由<code>Street</code> , <code>City</code> , <code>State</code>和<code>PostalCode</code>组成的<code>Address</code> 。 从数据库或API等系统读取此信息时,可以使用struct标记来控制如何将此信息分配给struct的字段。 结构标签是附加到结构字段的一小段元数据,这些元数据为与该结构一起使用的其他Go代码提供了指令。

<h2 id="what-does-a-struct-tag-look-like"> 结构标签是什么样的? <span style="font-weight: bold;">(</span>What Does a Struct Tag Look Like?<span style="font-weight: bold;">)</span></h2>

Go struct tags are annotations that appear after the type in a Go struct declaration. Each tag is composed of short strings associated with some corresponding value.

Go struct标签是在Go struct声明中的类型之后出现的注释。 每个标签由与一些相应值关联的短字符串组成。

A struct tag looks like this, with the tag offset with backtick <code>`</code> characters:

struct标签看起来像这样,标签的偏移量是反引号<code>`</code>字符:

<pre class="has"><code class="code-highlight language-go">type User struct { Name string `example:"name"` }</code></pre>

Other Go code is then capable of examining these structs and extracting the values assigned to specific keys it requests. Struct tags have no effect on the operation of your code without some other code that examines them.

然后其他Go代码能够检查这些结构并提取分配给它请求的特定键的值。 如果没有其他检查代码的结构标记,它们对代码的操作将没有任何影响。

Try this example to see what struct tags look like, and that without code from another package, they will have no effect.

尝试此示例以查看struct标记的外观,如果没有其他包中的代码,则它们将无效。

<pre class="has"><code class="code-highlight language-go">package main import "fmt" type User struct { Name string `example:"name"` } func (u *User) String() string { return fmt.Sprintf("Hi! My name is %s", u.Name) } func main() { u := &User{ Name: "Sammy", } fmt.Println(u) }</code></pre>

This will output:

这将输出:

<pre class="has"><code>
Output
Hi! My name is Sammy </code></pre>

This example defines a <code>User</code> type with a <code>Name</code> field. The <code>Name</code> field has been given a struct tag of <code>example:"name"</code>. We would refer to this specific tag in conversation as the “example struct tag” because it uses the word “example” as its key. The <code>example</code> struct tag has the value <code>"name"</code> for the <code>Name</code> field. On the <code>User</code> type, we also define the <code>String()</code> method required by the <code>fmt.Stringer</code> interface. This will be called automatically when we pass the type to <code>fmt.Println</code> and gives us a chance to produce a nicely formatted version of our struct.

本示例使用<code>Name</code>字段定义<code>User</code>类型。 “ <code>Name</code>字段已获得<code>example:"name"</code>的struct标签<code>example:"name"</code> 。 我们将会话中的这个特定标记称为“ example struct tag”,因为它使用单词“ example”作为其键。 该<code>example</code>结构的标签有值<code>"name"</code>的<code>Name</code>字段。 在<code>User</code>类型上,我们还定义了<code>fmt.Stringer</code>接口所需的<code>String()</code>方法。 当我们将类型传递给<code>fmt.Println</code>时,它将被自动<code>fmt.Println</code> ,这使我们有机会生成结构良好的格式化版本。

Within the body of <code>main</code>, we create a new instance of our <code>User</code> type and pass it to <code>fmt.Println</code>. Even though the struct had a struct tag present, we see that it has no effect on the operation of this Go code. It will behave exactly the same if the struct tag were not present.

在<code>main</code> ,我们创建一个<code>User</code>类型的新实例,并将其传递给<code>fmt.Println</code> 。 即使struct存在struct标记,我们仍然看到它对此Go代码的操作没有影响。 如果不存在struct标记,它将表现完全相同。

To use struct tags to accomplish something, other Go code must be written to examine structs at runtime. The standard library has packages that use struct tags as part of their operation. The most popular of these is the <code>encoding/json</code> package.

要使用struct标记完成某件事,必须编写其他Go代码以在运行时检查结构。 标准库包含使用struct标记作为其操作一部分的软件包。 其中最流行的是<code>encoding/json</code>包。

<h2 id="encoding-json"> 编码JSON <span style="font-weight: bold;">(</span>Encoding JSON<span style="font-weight: bold;">)</span></h2>

JavaScript Object Notation (JSON) is a textual format for encoding collections of data organized under different string keys. It’s commonly used to communicate data between different programs as the format is simple enough that libraries exist to decode it in many different languages. The following is an example of JSON:

JavaScript Object Notation(JSON)是一种文本格式,用于对根据不同字符串键组织的数据集合进行编码。 它通常用于在不同程序之间进行数据通信,因为其格式非常简单,以至于存在库可以用许多不同的语言对其进行解码。 以下是JSON的示例:

<pre class="has"><code class="code-highlight language-json">{ "language": "Go", "mascot": "Gopher" }</code></pre>

This JSON object contains two keys, <code>language</code> and <code>mascot</code>. Following these keys are the associated values. Here the <code>language</code> key has a value of <code>Go</code> and <code>mascot</code> is assigned the value <code>Gopher</code>.

此JSON对象包含两个键, <code>language</code>和<code>mascot</code> 。 这些键之后是关联的值。 此处, <code>language</code>键的值为<code>Go</code> , <code>mascot</code>的值为<code>Gopher</code> 。

The JSON encoder in the standard library makes use of struct tags as annotations indicating to the encoder how you would like to name your fields in the JSON output. These JSON encoding and decoding mechanisms can be found in the <code>encoding/json</code> package.

标准库中的JSON编码器使用struct标记作为注释,向编码器指示您希望如何在JSON输出中命名字段。 这些JSON编码和解码机制可以在<code>encoding/json</code> 包中找到 。

Try this example to see how JSON is encoded without struct tags:

请尝试以下示例,以了解如何在没有struct标签的情况下对JSON进行编码:

<pre class="has"><code class="code-highlight language-go">package main import ( "encoding/json" "fmt" "log" "os" "time" ) type User struct { Name string Password string PreferredFish []string CreatedAt time.Time } func main() { u := &User{ Name: "Sammy the Shark", Password: "fisharegreat", CreatedAt: time.Now(), } out, err := json.MarshalIndent(u, "", " ") if err != nil { log.Println(err) os.Exit(1) } fmt.Println(string(out)) }</code></pre>

This will print the following output:

这将打印以下输出:

<pre class="has"><code>
Output
{ "Name": "Sammy the Shark", "Password": "fisharegreat", "CreatedAt": "2019-09-23T15:50:01.203059-04:00" } </code></pre>

We defined a struct describing a user with fields including their name, password, and the time the user was created. Within the <code>main</code> function, we create an instance of this user by supplying values for all fields except <code>PreferredFish</code> (Sammy likes all fish). We then passed the instance of <code>User</code> to the <code>json.MarshalIndent</code> function. This is used so we can more easily see the JSON output without using an external formatting tool. This call could be replaced with <code>json.Marshal(u)</code> to receive JSON without any additional whitespace. The two additional arguments to <code>json.MarshalIndent</code> control the prefix to the output (which we have omitted with the empty string), and the characters to use for indenting, which here are two space characters. Any errors produced from <code>json.MarshalIndent</code> are logged and the program terminates using <code>os.Exit(1)</code>. Finally, we cast the <code>[]byte</code> returned from <code>json.MarshalIndent</code> to a <code>string</code> and hand the resulting string to <code>fmt.Println</code> for printing on the terminal.

我们定义了一个结构,该结构使用字段(包括用户名,密码和创建用户的时间)来描述用户。 在<code>main</code>功能中,我们通过为除<code>PreferredFish</code> (Sammy喜欢所有鱼)之外的所有字段提供值来创建此用户的实例。 然后,我们将<code>User</code>的实例传递给<code>json.MarshalIndent</code>函数。 使用它是为了让我们可以更轻松地查看JSON输出,而无需使用外部格式化工具。 此调用可以替换为<code>json.Marshal(u)</code>来接收JSON,而无需任何其他空格。 <code>json.MarshalIndent</code>的两个附加参数控制输出的前缀(我们使用空字符串省略了该前缀)以及用于缩进的字符,这是两个空格字符。 记录<code>json.MarshalIndent</code>产生的任何错误,并使用<code>os.Exit(1)</code>终止程序。 最后,我们将从<code>json.MarshalIndent</code>返回的<code>[]byte</code> <code>json.MarshalIndent</code>为<code>string</code> ,并将所得的字符串传递给<code>fmt.Println</code>以在终端上进行打印。

The fields of the struct appear exactly as we named them. This is not the typical JSON style that you may expect, which uses camel casing for names of fields. You’ll change the names of the field to follow camel case style in this next example. As you’ll see when you run this example, this won’t work because the desired field names conflict with Go’s rules about exported field names.

结构的字段与我们命名的字段完全相同。 这不是您可能期望的典型JSON样式,它使用驼峰式大小写字段名称。 在下一个示例中,您将更改字段名称以遵循驼峰样式。 正如您在运行此示例时所看到的那样,该操作将无效,因为所需的字段名称与Go的有关导出的字段名称的规则相冲突。

<pre class="has"><code class="code-highlight language-go">package main import ( "encoding/json" "fmt" "log" "os" "time" ) type User struct { name string password string preferredFish []string createdAt time.Time } func main() { u := &User{ name: "Sammy the Shark", password: "fisharegreat", createdAt: time.Now(), } out, err := json.MarshalIndent(u, "", " ") if err != nil { log.Println(err) os.Exit(1) } fmt.Println(string(out)) }</code></pre>

This will present the following output:

这将显示以下输出:

<pre class="has"><code>
Output
{} </code></pre>

In this version, we’ve altered the names of the fields to be camel cased. Now <code>Name</code> is <code>name</code>, <code>Password</code> is <code>password</code>, and finally <code>CreatedAt</code> is <code>createdAt</code>. Within the body of <code>main</code> we’ve changed the instantiation of our struct to use these new names. We then pass the struct to the <code>json.MarshalIndent</code> function as before. The output, this time is an empty JSON object, <code>{}</code>.

在此版本中,我们更改了驼峰式的字段名称。 现在<code>Name</code>是<code>name</code> , <code>Password</code>是<code>password</code> ,最后<code>CreatedAt</code>被<code>createdAt</code> 。 在<code>main</code>主体中,我们已更改结构的实例化以使用这些新名称。 然后,像以前一样,将结构传递给<code>json.MarshalIndent</code>函数。 这次的输出是一个空的JSON对象<code>{}</code> 。

Camel casing fields properly requires that the first character be lower-cased. While JSON doesn’t care how you name your fields, Go does, as it indicates the visibility of the field outside of the package. Since the <code>encoding/json</code> package is a separate package from the <code>main</code> package we’re using, we must uppercase the first character in order to make it visible to <code>encoding/json</code>. It would seem that we’re at an impasse, and we need some way to convey to the JSON encoder what we would like this field to be named.

骆驼的大小写正确要求第一个字符小写。 尽管JSON不在乎您如何命名字段,但Go会在乎,因为它表明了包外部字段的可见性。 由于<code>encoding/json</code>包是与我们正在使用的<code>main</code>包分开的包,因此我们必须将第一个字符大写以使其对<code>encoding/json</code>可见。 似乎我们陷入了僵局,我们需要某种方式将想要将此字段命名的内容传达给JSON编码器。

<h3 id="using-struct-tags-to-control-encoding"> 使用结构标签控制编码 <span style="font-weight: bold;">(</span>Using Struct Tags to Control Encoding<span style="font-weight: bold;">)</span></h3>

You can modify the previous example to have exported fields that are properly encoded with camel-cased field names by annotating each field with a struct tag. The struct tag that <code>encoding/json</code> recognizes has a key of <code>json</code> and a value that controls the output. By placing the camel-cased version of the field names as the value to the <code>json</code> key, the encoder will use that name instead. This example fixes the previous two attempts:

您可以修改前面的示例,以通过使用struct标记对每个字段进行注释,使导出的字段使用驼峰式字段名正确编码。 结构体标记, <code>encoding/json</code>识别具有一个键<code>json</code>和一个值,控制输出。 通过将字段名称的驼峰式版本作为<code>json</code>键的值,编码器将改为使用该名称。 本示例解决了前两次尝试:

<pre class="has"><code class="code-highlight language-go">package main import ( "encoding/json" "fmt" "log" "os" "time" ) type User struct { Name string `json:"name"` Password string `json:"password"` PreferredFish []string `json:"preferredFish"` CreatedAt time.Time `json:"createdAt"` } func main() { u := &User{ Name: "Sammy the Shark", Password: "fisharegreat", CreatedAt: time.Now(), } out, err := json.MarshalIndent(u, "", " ") if err != nil { log.Println(err) os.Exit(1) } fmt.Println(string(out)) }</code></pre>

This will output:

这将输出:

<pre class="has"><code>
Output
{ "name": "Sammy the Shark", "password": "fisharegreat", "preferredFish": null, "createdAt": "2019-09-23T18:16:17.57739-04:00" } </code></pre>

We’ve changed the field names back to be visible to other packages by capitalizing the first letters of their names. However, this time we’ve added struct tags in the form of <code>json:"name"</code>, where <code>"name"</code> was the name we wanted <code>json.MarshalIndent</code> to use when printing our struct as JSON.

我们通过将字段名称的首字母大写更改为其他软件包可以看到的字段名称。 但是,这次我们以<code>json:"name"</code>的形式添加了struct标记,其中<code>"name"</code>是我们想要的<code>json.MarshalIndent</code>在将struct打印为JSON时使用的名称。

We’ve now successfully formatted our JSON correctly. Notice, however, that the fields for some values were printed even though we did not set those values. The JSON encoder can eliminate these fields as well, if you like.

现在,我们已经成功地正确格式化了JSON。 但是请注意,即使我们没有设置这些值,某些值的字段也会被打印出来。 如果您愿意,JSON编码器也可以消除这些字段。

<h3 id="removing-empty-json-fields"> 删除空的JSON字段 <span style="font-weight: bold;">(</span>Removing Empty JSON Fields<span style="font-weight: bold;">)</span></h3>

Most commonly, we want to suppress outputting fields that are unset in JSON. Since all types in Go have a “zero value,” some default value that they are set to, the <code>encoding/json</code> package needs additional information to be able to tell that some field should be considered unset when it assumes this zero value. Within the value part of any <code>json</code> struct tag, you can suffix the desired name of your field with <code>,omitempty</code> to tell the JSON encoder to suppress the output of this field when the field is set to the zero value. The following example fixes the previous examples to no longer output empty fields:

最常见的是,我们要禁止输出未在JSON中设置的字段。 由于Go中的所有类型都有一个“零值”(它们被设置为一些默认值),所以<code>encoding/json</code>包需要其他信息,以便能够在假定该字段为零时将某些字段视为未设置。 在任何<code>json</code> struct标记的value部分中,您可以在字段后缀所需的名称<code>,omitempty</code>告诉JSON编码器在该字段设置为零值时禁止显示该字段的输出。 下面的示例将前面的示例修复为不再输出空字段:

<pre class="has"><code class="code-highlight language-go">package main import ( "encoding/json" "fmt" "log" "os" "time" ) type User struct { Name string `json:"name"` Password string `json:"password"` PreferredFish []string `json:"preferredFish,omitempty"` CreatedAt time.Time `json:"createdAt"` } func main() { u := &User{ Name: "Sammy the Shark", Password: "fisharegreat", CreatedAt: time.Now(), } out, err := json.MarshalIndent(u, "", " ") if err != nil { log.Println(err) os.Exit(1) } fmt.Println(string(out)) }</code></pre>

This example will output:

此示例将输出:

<pre class="has"><code>
Output
{ "name": "Sammy the Shark", "password": "fisharegreat", "createdAt": "2019-09-23T18:21:53.863846-04:00" } </code></pre>

We’ve modified the previous examples so that the <code>PreferredFish</code> field now has the struct tag <code>json:"preferredFish,omitempty"</code>. The presence of the <code>,omitempty</code> augmentation causes the JSON encoder to skip that field, since we decided to leave it unset. This had the value <code>null</code> in our previous examples’ outputs.

我们已经修改了前面的示例,以便<code>PreferredFish</code>字段现在具有struct标签<code>json:"preferredFish,omitempty"</code> 。 由于我们决定不设置该字段,因此<code>,omitempty</code>扩充的存在会导致JSON编码器跳过该字段。 在我们先前示例的输出中,其值为<code>null</code> 。

This output is looking much better, but we’re still printing out the user’s password. The <code>encoding/json</code> package provides another way for us to ignore private fields entirely.

该输出看起来要好得多,但我们仍在打印用户密码。 <code>encoding/json</code>包为我们提供了另一种完全忽略私有字段的方法。

<h3 id="ignoring-private-fields"> 忽略私有字段 <span style="font-weight: bold;">(</span>Ignoring Private Fields<span style="font-weight: bold;">)</span></h3>

Some fields must be exported from structs so that other packages can correctly interact with the type. However, the nature of these fields may be sensitive, so in these circumstances, we would like the JSON encoder to ignore the field entirely—even when it is set. This is done using the special value <code>-</code> as the value argument to a <code>json:</code> struct tag.

必须从结构导出某些字段,以便其他包可以与类型正确交互。 但是,这些字段的性质可能很敏感,因此在这种情况下,我们希望JSON编码器完全忽略该字段,即使设置了该字段也是如此。 这是通过使用特殊值<code>-</code>作为<code>json:</code> struct标记的value参数来完成的。

This example fixes the issue of exposing the user’s password.

本示例解决了公开用户密码的问题。

<pre class="has"><code class="code-highlight language-go">package main import ( "encoding/json" "fmt" "log" "os" "time" ) type User struct { Name string `json:"name"` Password string `json:"-"` CreatedAt time.Time `json:"createdAt"` } func main() { u := &User{ Name: "Sammy the Shark", Password: "fisharegreat", CreatedAt: time.Now(), } out, err := json.MarshalIndent(u, "", " ") if err != nil { log.Println(err) os.Exit(1) } fmt.Println(string(out)) }</code></pre>

When you run this example, you’ll see this output:

运行此示例时,将看到以下输出:

<pre class="has"><code>
Output
{ "name": "Sammy the Shark", "createdAt": "2019-09-23T16:08:21.124481-04:00" } </code></pre>

The only thing we’ve changed in this example from previous ones is that the password field now uses the special <code>"-"</code> value for its <code>json:</code> struct tag. We see that in the output from this example that the <code>password</code> field is no longer present.

在本示例中,我们从以前的示例中唯一更改的是,密码字段现在为其<code>json:</code> struct标记使用特殊的<code>"-"</code>值。 我们在此示例的输出中看到, <code>password</code>字段不再存在。

These features of the <code>encoding/json</code> package, <code>,omitempty</code> and <code>"-"</code>, are not standards. What a package decides to do with values of a struct tag depends on its implementation. Because the <code>encoding/json</code> package is part of the standard library, other packages have also implemented these features in the same way as a matter of convention. However, it’s important to read the documentation for any third-party package that uses struct tags to learn what is supported and what is not.

<code>encoding/json</code>包的这些功能<code>,omitempty</code>和<code>"-"</code>不是标准的。 包决定使用struct标记的值的方式取决于其实现。 因为<code>encoding/json</code>包是标准库的一部分,所以其他包也按照约定的相同方式实现了这些功能。 但是,阅读任何使用struct标记的第三方程序包的文档以了解支持的内容和不支持的内容非常重要。

<h2 id="conclusion"> 结论 <span style="font-weight: bold;">(</span>Conclusion<span style="font-weight: bold;">)</span></h2>

Struct tags offer a powerful means to augment the functionality of code that works with your structs. Many standard library and third-party packages offer ways to customize their operation through the use of struct tags. Using them effectively in your code provides both this customization behavior and succinctly documents how these fields are used to future developers.

结构标签提供了一种强大的手段来增强与您的结构一起使用的代码的功能。 许多标准库和第三方软件包都提供了使用struct标记自定义其操作的方法。 在您的代码中有效地使用它们提供了这种自定义行为,并简洁地记录了如何将这些字段用于将来的开发人员。

<blockquote>

翻译自: https://www.digitalocean.com/community/tutorials/how-to-use-struct-tags-in-go

</blockquote>

golang 结构体标签

到此这篇关于“golang 结构体标签_如何在Go中使用结构标签”的文章就介绍到这了,更多文章或继续浏览下面的相关文章,希望大家以后多多支持JQ教程网!

您可能感兴趣的文章:
H标签对页面优化的影响使用
Golang结构体中Tag的使用
html5页面结构的变化以及增加和删除标签的总结
HTML5中的header标签是什么意思?HTML5中header标签具体使用方法你知道吗?
Go 反射机制介绍
html5 header标签怎么用?html5 header标签的作用介绍
HTML5语义化总结
html5 header标签是什么意思?html5 header标签的用法详解(附实例)
html5 source标签怎么用?html5 source标签属性介绍
Go 学习笔记 09 | Golang 结构体与 JSON 互相转换

[关闭]
~ ~