2.2. 常用注意事项 1到7 基础

未匹配的标注

g g study,d d up!

常用注意事项

1. 结构体的字段可以是任何类型,包括基本类型,指针类型和其他结构体类型等。

package main

import "fmt"

type Person struct {
    name string
    age  int
    address *Address
}

type Address struct {
    street string
    city   string
}

func main() {
    p := Person{name: "Alice", age: 30, address: &Address{street: "123 Main St", city: "Anytown"}}
    fmt.Println(p.name)
    fmt.Println(p.age)
    fmt.Println(p.address.street)
    fmt.Println(p.address.city)
}

在这个例子中,我们定义了两个结构体类型:PersonAddressPerson结构体具有三个字段:name是字符串类型,age是整数类型,address是指向Address结构体的指针类型。Address结构体具有两个字段:streetcity,都是字符串类型。

main()函数中,我们创建了一个Person结构体的实例,并为每个字段设置了值。然后,我们使用点运算符访问每个字段并打印它们的值。

2. 结构体的字段名称可以是任何有效的标识符,且每个字段必须有一个唯一的名称。

名称重复就报错。这里不演示了。如果录制视频,我就在这演示一下,现在是文档你自己复制代码,整两个name 试试看。

3. 结构体可以嵌套,这意味着一个结构体可以包含其他结构体类型的字段。

当我们创建结构体时,我们可以将其他结构体类型嵌套到当前结构体中,形成嵌套结构体。

下面是一个简单的例子,其中定义了两个结构体:PersonEmployee,其中 Employee 结构体嵌套了 Person 结构体。

type Person struct {
    name    string
    age     int
    address string
}

type Employee struct {
    id     int
    salary float64
    person Person
}

func main() {
    p := Person{"Tom", 25, "123 Main Street"}
    e := Employee{1, 5000.0, p}
    fmt.Println(e.id, e.salary, e.person.name, e.person.age, e.person.address)
}

在上面的示例中,Employee 结构体嵌套了 Person 结构体,并使用 person 字段来存储 Person 结构体的值。在 main() 函数中,我们创建了一个 Person 类型的值 p,并将其传递给 Employee 结构体的 person 字段。最后,我们使用 fmt.Println() 函数打印 Employee 结构体的所有字段。

4. 可以使用结构体字面值初始化结构体变量。例如,可以使用以下方式初始化Person结构体变量:

person := Person{name: "Alice", age: 25}

5. 结构体可以作为函数参数和返回值。如果结构体很大,最好通过指针传递,以避免复制整个结构体。

在Go中,结构体是一种非常常见的数据类型,我们经常需要将结构体作为函数参数传递,或者将结构体作为函数的返回值。

如果结构体很大,传递结构体的值将占用大量内存,并且会带来性能问题。在这种情况下,最好通过指针传递结构体,因为指针只是一个指向内存中的位置的引用,而不是复制整个结构体。这将减少内存的使用,并提高程序的性能。

例如,考虑以下结构体类型:

type Person struct {
    Name string
    Age  int
    ...
}

如果我们需要在函数中修改一个非常大的Person对象,最好使用指针来传递它,以避免复制整个结构体:

func updatePerson(p *Person) {
    p.Age = 30
    ...
}

func main() {
    person := &Person{Name: "John", Age: 25, ...}
    updatePerson(person)
    ...
}

在这个例子中,我们将指向Person结构体的指针传递给函数updatePerson,这将避免复制整个结构体,并且允许函数修改原始对象的值。

6. 结构体的字段可以使用标签(tag)进行注释。标签是在字段后面用反引号括起来的字符串,可以用于给字段提供元数据信息。

下面是一个使用结构体标签的简单示例,其中使用标签为结构体中的字段提供了名称和其他元数据信息:

package main

import (
    "fmt"
    "reflect"
)

type Person struct {
    Name    string `json:"name" db:"full_name"`
    Age     int    `json:"age" db:"age"`
    Address string `json:"address,omitempty" db:"address"`
}

func main() {
    p := Person{
        Name:    "John",
        Age:     30,
        Address: "123 Main St",
    }
    t := reflect.TypeOf(p)
    for i := 0; i < t.NumField(); i++ {
        field := t.Field(i)
        fmt.Printf("%s: %s\n", field.Tag.Get("json"), field.Tag.Get("db"))
    }
}

在上面的示例中,我们定义了一个名为 Person 的结构体,该结构体有三个字段:NameAgeAddress。每个字段都有一个标签,分别是 jsondb。在 main 函数中,我们创建了一个 Person 实例,并使用反射获取结构体的类型信息。然后,我们遍历结构体中的字段,使用 Tag.Get 方法获取每个字段的 jsondb 标签,并打印出来。输出结果如下:

name: full_name
age: age
address: address,omitempty

从输出结果可以看出,我们可以使用标签为结构体中的字段提供元数据信息,这些元数据信息可以在编写代码时使用,比如用于序列化和反序列化、ORM 框架等。

7. 如果结构体的字段名以大写字母开头,则表示该字段是公共字段,可以在其他包中访问。如果字段名以小写字母开头,则表示该字段是私有字段,只能在同一个包中访问。

下面是一个简单的demo,其中Person结构体有一个公共字段Name和一个私有字段age

package main

import "fmt"

type Person struct {
    Name string // 公共字段
    age  int    // 私有字段
}

func main() {
    p := Person{Name: "John", age: 30}
    fmt.Println(p.Name) // 可以访问公共字段
    // fmt.Println(p.age) // 无法访问私有字段
}

可以看到,我们可以在main包中访问Person结构体的公共字段Name,但无法访问其私有字段age。如果我们取消注释fmt.Println(p.age),编译器就会报错。

欢迎关注公众号上海php自学中心,一起交流。

本文章首发在 LearnKu.com 网站上。

上一篇 下一篇
讨论数量: 0
发起讨论 只看当前版本


暂无话题~