go语言结构体数组定义
介绍 (Introduction)
Building abstractions around concrete details is the greatest tool that a programming language can give to a developer. Structs allow Go developers to describe the world in which a Go program operates. Instead of reasoning about strings describing a Street
, City
, or a PostalCode
, structs allow us to instead talk about an Address
. They serve as a natural nexus for documentation in our efforts to tell future developers (ourselves included) what data is important to our Go programs and how future code should use that data appropriately. Structs can be defined and used in a few different ways. In this tutorial, we’ll take a look at each of these techniques.
围绕具体细节构建抽象是编程语言可以提供给开发人员的最大工具。 结构允许Go开发人员描述Go程序在其中运行的世界。 结构使我们无需再讨论描述Street
, City
或City
字符串, PostalCode
我们可以谈论Address
。 它们是文档的自然纽带,可以帮助我们告诉未来的开发人员(包括我们自己)哪些数据对我们的Go程序很重要,以及将来的代码应如何适当地使用这些数据。 可以以几种不同的方式定义和使用结构。 在本教程中,我们将研究每种技术。
定义结构 (Defining Structs)
Structs work like paper forms that you might use, for example, to file your taxes. Paper forms might have fields for textual pieces of information like your first and last names. Besides text fields, forms might have checkboxes to indicate Boolean values such as “married” or “single,” or date fields for birth date. Similarly, structs collect different pieces of data together and organize them under different field names. When you initialize a variable with a new struct, it’s as though you’ve photocopied a form and made it ready to fill out.
结构的工作方式类似于纸质表格,例如,您可以用来报税。 纸质表格可能包含文本信息字段,例如您的名字和姓氏。 除文本字段外,表单还可能具有复选框,以指示布尔值(例如“已婚”或“单身”)或生日字段的日期字段。 同样,结构将不同的数据收集在一起,并以不同的字段名称进行组织。 当您使用新的结构体初始化变量时,就好像您已经将表格影印并准备好填写一样。
To create a new struct, you must first give Go a blueprint that describes the fields the struct contains. This struct definition usually begins with the keyword type
followed by the name of the struct. After this, use the struct
keyword followed by a pair of braces {}
where you declare the fields the struct will contain. Once you have defined the struct, you are then able to declare variables that use this struct definition. This example defines a struct and uses it:
要创建新结构,您必须首先给Go一张蓝图,该蓝图描述该结构包含的字段。 此结构定义通常以关键字type
开头,后跟结构名称。 之后,使用struct
关键字,后跟一对大括号{}
,在其中声明该结构将包含的字段。 定义结构后,便可以声明使用此结构定义的变量。 本示例定义一个结构并使用它:
package main
import "fmt"
type Creature struct {
Name string
}
func main() {
c := Creature{
Name: "Sammy the Shark",
}
fmt.Println(c.Name)
}
When you run this code, you will see this output:
运行此代码时,将看到以下输出:
output
Sammy the Shark
We first define a Creature
struct in this example, containing a Name
field of type string
. Within the body of main
, we create an instance of Creature
by placing a pair of braces after the name of the type, Creature
, and then specifying values for that instance’s fields. The instance in c
will have its Name
field set to “Sammy the Shark”. Within the fmt.Println
function invocation, we retrieve the values of the instance’s field by placing a period after the variable where the instance was created, followed by the name of the field we would like to access. For example, c.Name
in this case returns the Name
field.
在此示例中,我们首先定义一个Creature
结构,其中包含string
类型的Name
字段。 在体内main
,我们创建的实例Creature
通过放置一对大括号的类型,名称后的Creature
,然后该实例的字段中指定的值。 c
的实例的“ Name
字段将设置为“ Sammy the Shark”。 在fmt.Println
函数调用中,我们通过在创建实例的变量之后放置一个句点,然后加上要访问的字段名称,来检索实例字段的值。 例如,在这种情况下, c.Name
返回“ Name
字段。
When you declare a new instance of a struct, you generally enumerate the field names with their values, as in the last example. Alternatively, if every field value will be provided during the instantiation of a struct, you can omit the field names, like in this example:
声明一个新的结构实例时,通常像上一个示例一样枚举字段名称及其值。 另外,如果在结构化实例化过程中将提供每个字段值,则可以省略字段名称,如以下示例所示:
package main
import "fmt"
type Creature struct {
Name string
Type string
}
func main() {
c := Creature{"Sammy", "Shark"}
fmt.Println(c.Name, "the", c.Type)
}
The output is the same as the last example:
输出与上一个示例相同:
output
Sammy the Shark
We’ve added an extra field to Creature
to track the Type
of creature as a string
. When instantiating Creature
within the body of main
, we’ve opted to use the shorter instantiation form by providing values for each field in order and omitting their field names. In the declaration Creature{"Sammy", "Shark"}
, the Name
field takes the value Sammy
and the Type
field takes the value Shark
because Name
appears first in the type declaration, followed by Type
.
我们在Creature
添加了一个额外的字段,以string
跟踪Creature
的Type
。 在main
主体中实例化Creature
,我们选择使用较短的实例化形式,方法是按顺序为每个字段提供值,并省略其字段名称。 在声明Creature{"Sammy", "Shark"}
, Name
字段取值Sammy
,而Type
字段取值Shark
因为Name
出现在类型声明中,然后是Type
。
This shorter declaration form has a few drawbacks that have led the Go community to prefer the longer form in most circumstances. You must provide values for each field in the struct when using the short declaration—you can’t skip fields you don’t care about. This quickly causes short declarations for structs with many fields to become confusing. For this reason, declaring structs using the short form is typically used with structs that have few fields.
这种较短的声明形式有一些缺点,导致Go社区在大多数情况下都喜欢较长的形式。 使用简短声明时,必须为结构中的每个字段提供值-您不能跳过不需要的字段。 这很快导致具有许多字段的结构的简短声明变得令人困惑。 由于这个原因,通常使用简短形式声明结构与字段很少的结构一起使用。
The field names in the examples so far have all begun with capital letters. This is more significant than a stylistic preference. The use of capital or lowercase letters for field names affects whether your field names will be accessible to code running in other packages.
到目前为止,示例中的字段名称都以大写字母开头。 这比风格偏好更重要。 字段名使用大写或小写字母会影响您在其他程序包中运行的代码是否可以访问您的字段名。
结构字段导出 (Struct Field Exporting)
Fields of a struct follow the same exporting rules as other identifiers within the Go programming language. If a field name begins with a capital letter, it will be readable and writeable by code outside of the package where the struct was defined. If the field begins with a lowercase letter, only code within that struct’s package will be able to read and write that field. This example defines fields that are exported and those that are not:
结构字段与Go编程语言中的其他标识符遵循相同的导出规则。 如果字段名以大写字母开头,则定义该结构的包外部的代码将可对其进行读写。 如果该字段以小写字母开头,则只有该结构包中的代码才能读取和写入该字段。 本示例定义了导出的字段和未导出的字段:
package main
import "fmt"
type Creature struct {
Name string
Type string
password string
}
func main() {
c := Creature{
Name: "Sammy",
Type: "Shark",
password: "secret",
}
fmt.Println(c.Name, "the", c.Type)
fmt.Println("Password is", c.password)
}
This will output:
这将输出:
output
Sammy the Shark
Password is secret
We added an additional field to our previous examples, secret
. secret
is an unexported string
field, which means that any other package that attempts to instantiate a Creature
will not be able to access or set its secret
field. Within the same package, we are able to access these fields, as this example has done. Since main
is also in the main
package, it’s able to reference c.password
and retrieve the value stored there. It’s common to have unexported fields in structs with access to them mediated by exported methods.
我们在前面的示例中添加了另一个字段secret
。 secret
是未导出的string
字段,这意味着任何其他尝试实例化Creature
程序包将无法访问或设置其secret
字段。 在同一个程序包中,我们可以访问这些字段,如本示例所示。 由于main
也在main
软件包中,因此它可以引用c.password
并检索存储在其中的值。 通常在结构中具有未导出的字段,并通过导出的方法来访问它们。
内联结构 (Inline Structs)
In addition to defining a new type to represent a struct, you can also define an inline struct. These on-the-fly struct definitions are useful in situations where inventing new names for struct types would be wasted effort. For example, tests often use a struct to define all the parameters that make up a particular test case. It would be cumbersome to come up with new names like CreatureNamePrintingTestCase
when that struct is used in only one place.
除了定义表示结构的新类型外,还可以定义内联结构。 这些动态结构定义在浪费结构类型的新名称的情况下很有用。 例如,测试通常使用结构来定义构成特定测试用例的所有参数。 当仅在一个地方使用该结构时,想出像CreatureNamePrintingTestCase
这样的新名称将很麻烦。
Inline struct definitions appear on the right-hand side of a variable assignment. You must provide an instantiation of them immediately after by providing an additional pair of braces with values for each of the fields you define. The example that follows shows an inline struct definition:
内联结构定义出现在变量分配的右侧。 您必须在为每个定义的字段提供另外一对带有值的括号之后,立即对其进行实例化。 以下示例显示了内联结构定义:
package main
import "fmt"
func main() {
c := struct {
Name string
Type string
}{
Name: "Sammy",
Type: "Shark",
}
fmt.Println(c.Name, "the", c.Type)
}
The output from this example will be:
该示例的输出将是:
output
Sammy the Shark
Rather than defining a new type describing our struct with the type
keyword, this example defines an inline struct by placing the struct
definition immediately following the short-assignment operator, :=
. We define the fields of the struct as in previous examples, but then we must immediately supply another pair of braces and the values that each field will assume. Using this struct is now exactly the same as before—we can refer to field names using dot notation. The most common place you will see inline structs declared is during tests, as frequently one-off structs are defined to contain data and expectations for a particular test case.
本示例没有使用type
关键字定义描述我们的结构的新类型,而是通过将struct
定义紧紧放置在short-assignment运算符:=
之struct
定义内联结构。 正如前面的示例中那样,我们定义了结构的字段,但随后必须立即提供另一对大括号以及每个字段将采用的值。 现在使用此结构与以前完全相同,我们可以使用点表示法来引用字段名称。 您将看到的内联结构最常见的地方是在测试期间,因为经常将一次性结构定义为包含特定测试用例的数据和期望。
结论 (Conclusion)
Structs are collections of heterogenous data defined by programmers to organize information. Most programs deal with enormous volumes of data, and without structs, it would become difficult to remember which string
or int
variables belonged together or which were different. The next time that you find yourself juggling groups of variables, ask yourself if perhaps those variables would be better grouped together using a struct
. Those variables may have been describing some higher-level concept all along.
结构是程序员定义的用于组织信息的异构数据的集合。 大多数程序处理大量数据,并且没有结构,将很难记住哪些string
或int
变量属于一起或哪些不同。 下次您发现自己要弄乱变量组时,问问自己,也许最好使用struct
将这些变量组合在一起。 这些变量可能一直都在描述一些更高级的概念。
翻译自: https://www.digitalocean.com/community/tutorials/defining-structs-in-go
go语言结构体数组定义