一、Go基础知识15、结构体详解

本文详细介绍了Go语言中type关键字的使用,包括定义新类型(如int别名、结构体、接口和函数类型)、结构体的定义、初始化(包括字段名初始化和零值初始化)、匿名结构体、结构体嵌套以及方法的定义和接收者。
摘要由CSDN通过智能技术生成

一、type关键字

在Go语言中,type关键字用于定义新的类型或为已有类型创建别名。它可以用于定义结构体、接口、函数类型等。

1、定义新的数据类型

type MyInt int

func main() {
    var num MyInt = 42
    fmt.Println(num)
}

解释
这里通过type关键字将MyInt定义为int的别名,然后创建一个变量num,并将其赋值为42。这样,MyInt就成为了一个新的类型,可以用于声明变量。

2、定义结构体

type Person struct {
    FirstName string
    LastName  string
}

func main() {
    p := Person{FirstName: "John", LastName: "Doe"}
    fmt.Println(p.FirstName, p.LastName)
}

解释
通过type关键字定义了一个名为Person的结构体,其中包含FirstNameLastName两个字段。在main函数中创建了一个Person类型的变量p并初始化其字段。

3、定义接口

type Shape interface {
    Area() float64
}

type Circle struct {
    Radius float64
}

func (c Circle) Area() float64 {
    return math.Pi * c.Radius * c.Radius
}

func printArea(s Shape) {
    fmt.Println("Area:", s.Area())
}

func main() {
    circle := Circle{Radius: 5}
    printArea(circle)
}

解释
在这个例子中,通过type关键字定义了一个接口Shape,该接口包含一个Area方法。然后,定义了一个Circle结构体,并为其实现了Area方法。最后,在main函数中创建了一个Circle类型的变量,并通过printArea函数打印其面积。

4、定义函数类型

type MathFunc func(float64, float64) float64

func add(x, y float64) float64 {
    return x + y
}

func subtract(x, y float64) float64 {
    return x - y
}

func main() {
    var operation MathFunc
    operation = add
    result := operation(3, 2)
    fmt.Println("Addition:", result)

    operation = subtract
    result = operation(3, 2)
    fmt.Println("Subtraction:", result)
}

解释
在这个例子中,通过type关键字定义了一个名为MathFunc的函数类型,它接受两个float64参数并返回一个float64值。然后,定义了两个函数addsubtract,并在main函数中演示如何使用该函数类型来引用不同的操作。

二、结构体的定义与初始化

在Go语言中,结构体是一种自定义的数据类型,用于封装一组不同类型的数据字段。结构体通过type关键字定义,并使用struct关键字声明。

1、定义结构体

type Person struct {
    FirstName string
    LastName  string
    Age       int
    Address   Address // 嵌套结构体
}

type Address struct {
    Street  string
    City    string
    ZipCode string
}

解释
在这个例子中,定义了一个名为Person的结构体,它包含了FirstNameLastNameAgeAddress字段。Address字段是另一个名为Address的结构体,展示了结构体可以进行嵌套。

2、初始化结构体

方法一:使用字段名初始化

func main() {
    person := Person{
        FirstName: "Alice",
        LastName:  "Smith",
        Age:       30,
        Address: Address{
            Street:  "123 Main St",
            City:    "New York",
            ZipCode: "10001",
        },
    }
    fmt.Println(person.FirstName, person.LastName, person.Age)
    fmt.Println("Address:", person.Address.Street, person.Address.City, person.Address.ZipCode)
}

解释
这里通过指定每个字段的名称和对应的值来初始化Person结构体。然后,输出了Person结构体的各个字段值。

方法二:使用零值初始化并逐一赋值

func main() {
    var person Person
    person.FirstName = "Bob"
    person.LastName = "Johnson"
    person.Age = 25
    person.Address.Street = "456 Elm St"
    person.Address.City = "San Francisco"
    person.Address.ZipCode = "94107"

    fmt.Println(person.FirstName, person.LastName, person.Age)
    fmt.Println("Address:", person.Address.Street, person.Address.City, person.Address.ZipCode)
}

解释
在这个例子中,首先使用var关键字声明了一个Person类型的变量person,它将被初始化为零值。然后,逐一对其字段进行赋值。

3、匿名结构体

func main() {
    person := struct {
        Name    string
        Age     int
        Country string
    }{
        Name:    "Eva",
        Age:     28,
        Country: "Spain",
    }
    fmt.Println(person)
}

解释
这个例子展示了如何在不定义结构体名称的情况下直接创建匿名结构体,并对其进行初始化。

4、结构体指针

func main() {
    personPtr := &Person{
        FirstName: "David",
        LastName:  "Brown",
        Age:       35,
        Address: Address{
            Street:  "789 Pine St",
            City:    "Los Angeles",
            ZipCode: "90001",
        },
    }
    fmt.Println(*personPtr)
}

解释
在Go中,可以使用&操作符获取结构体的指针。这个例子中,personPtr是一个指向Person结构体的指针,通过&Person{}进行初始化,并使用*操作符对指针进行解引用以访问结构体的值。

三、匿名结构体

在Go语言中,匿名结构体是一种不具有结构体类型名称的结构体。它通常在创建临时的、仅在局部范围内使用的结构体时非常有用。匿名结构体不需要通过type关键字定义,可以直接在使用的地方进行结构体字段的声明和初始化。

1、基本语法

package main

import "fmt"

func main() {
    // 匿名结构体的定义和初始化
    person := struct {
        FirstName string
        LastName  string
        Age       int
    }{
        FirstName: "Alice",
        LastName:  "Smith",
        Age:       30,
    }

    // 访问匿名结构体的字段
    fmt.Println("Name:", person.FirstName, person.LastName)
    fmt.Println("Age:", person.Age)
}

解释
在这个例子中,通过struct{}定义了一个匿名结构体,并在结构体内部声明了FirstNameLastNameAge字段。然后,通过{}对结构体进行初始化,并为字段赋值。最后,通过.操作符访问结构体的字段。

2、匿名结构体作为函数参数

package main

import "fmt"

func printPerson(person struct {
    FirstName string
    LastName  string
    Age       int
}) {
    fmt.Println("Name:", person.FirstName, person.LastName)
    fmt.Println("Age:", person.Age)
}

func main() {
    // 传递匿名结构体作为函数参数
    printPerson(struct {
        FirstName string
        LastName  string
        Age       int
    }{
        FirstName: "Bob",
        LastName:  "Johnson",
        Age:       25,
    })
}

解释
在这个例子中,定义了一个函数printPerson,它接受一个匿名结构体作为参数,并在函数内部打印结构体的字段。在main函数中调用printPerson时,直接通过struct{}创建匿名结构体并进行初始化。

3、匿名结构体嵌套

package main

import "fmt"

func main() {
    // 嵌套匿名结构体
    employee := struct {
        Person struct {
            FirstName string
            LastName  string
            Age       int
        }
        Department string
    }{
        Person: struct {
            FirstName string
            LastName  string
            Age       int
        }{
            FirstName: "John",
            LastName:  "Doe",
            Age:       35,
        },
        Department: "Engineering",
    }

    // 访问嵌套匿名结构体的字段
    fmt.Println("Name:", employee.Person.FirstName, employee.Person.LastName)
    fmt.Println("Age:", employee.Person.Age)
    fmt.Println("Department:", employee.Department)
}

解释
这个例子演示了如何在结构体内部嵌套匿名结构体。employee结构体包含了一个名为Person的匿名结构体,并在main函数中进行了初始化。通过.操作符访问嵌套结构体的字段。

4、匿名结构体和切片结合

package main

import "fmt"

func main() {
    // 使用匿名结构体和切片结合
    people := []struct {
        FirstName string
        LastName  string
        Age       int
    }{
        {"Alice", "Smith", 30},
        {"Bob", "Johnson", 25},
        {"Eva", "Davis", 28},
    }

    // 遍历切片并输出每个人的信息
    for _, person := range people {
        fmt.Println("Name:", person.FirstName, person.LastName)
        fmt.Println("Age:", person.Age)
        fmt.Println("----")
    }
}

解释
在这个例子中,创建了一个包含匿名结构体的切片people,并使用切片字面量初始化。然后,通过range循环遍历切片并输出每个人的信息。

注意
匿名结构体在一些场景下可以提高代码的简洁性和可读性,特别是在临时数据结构的定义和使用时。

四、结构体嵌套

在Go语言中,结构体嵌套是一种将一个结构体类型嵌套到另一个结构体类型中的方式。这种嵌套可以帮助组织和模块化代码,使其更具可读性和可维护性。

1、基本的结构体嵌套

package main

import "fmt"

// 定义 Address 结构体
type Address struct {
    Street  string
    City    string
    ZipCode string
}

// 定义 Person 结构体,嵌套 Address 结构体
type Person struct {
    FirstName string
    LastName  string
    Age       int
    HomeAddress Address // 结构体嵌套
}

func main() {
    // 创建 Person 结构体实例
    person := Person{
        FirstName: "John",
        LastName:  "Doe",
        Age:       30,
        HomeAddress: Address{
            Street:  "123 Main St",
            City:    "New York",
            ZipCode: "10001",
        },
    }

    // 访问嵌套结构体的字段
    fmt.Println("Name:", person.FirstName, person.LastName)
    fmt.Println("Age:", person.Age)
    fmt.Println("Home Address:", person.HomeAddress.Street, person.HomeAddress.City, person.HomeAddress.ZipCode)
}

解释
在这个例子中,定义了两个结构体 AddressPersonPerson 结构体中嵌套了 Address 结构体。创建 Person 结构体实例时,通过嵌套的方式,可以直接访问 Address 结构体的字段。

2、结构体嵌套和匿名结构体

package main

import "fmt"

// 定义 Address 结构体
type Address struct {
    Street  string
    City    string
    ZipCode string
}

// 定义 Person 结构体,嵌套匿名结构体
type Person struct {
    FirstName string
    LastName  string
    Age       int
    Address   // 匿名结构体嵌套
}

func main() {
    // 创建 Person 结构体实例
    person := Person{
        FirstName: "Alice",
        LastName:  "Smith",
        Age:       25,
        Address: Address{
            Street:  "456 Elm St",
            City:    "San Francisco",
            ZipCode: "94107",
        },
    }

    // 访问嵌套结构体的字段
    fmt.Println("Name:", person.FirstName, person.LastName)
    fmt.Println("Age:", person.Age)
    fmt.Println("Address:", person.Street, person.City, person.ZipCode)
}

解释
在这个例子中,Person 结构体嵌套了一个匿名的 Address 结构体。在创建 Person 结构体实例时,可以直接访问匿名结构体 Address 的字段。

3、结构体嵌套和方法

package main

import "fmt"

// 定义 Address 结构体
type Address struct {
    Street  string
    City    string
    ZipCode string
}

// 定义 Person 结构体,嵌套 Address 结构体
type Person struct {
    FirstName string
    LastName  string
    Age       int
    HomeAddress Address
}

// 定义 Person 结构体的方法
func (p Person) PrintAddress() {
    fmt.Println("Home Address:", p.HomeAddress.Street, p.HomeAddress.City, p.HomeAddress.ZipCode)
}

func main() {
    // 创建 Person 结构体实例
    person := Person{
        FirstName: "Bob",
        LastName:  "Johnson",
        Age:       35,
        HomeAddress: Address{
            Street:  "789 Pine St",
            City:    "Los Angeles",
            ZipCode: "90001",
        },
    }

    // 调用嵌套结构体的方法
    person.PrintAddress()
}

解释
在这个例子中,Person 结构体嵌套了 Address 结构体,并定义了 Person 结构体的方法 PrintAddress,用于打印嵌套结构体 Address 的字段。在 main 函数中创建 Person 结构体实例,然后调用方法打印地址信息。

五、结构体定义方法

在Go语言中,结构体可以定义方法,这些方法可以在结构体上调用。方法是一种与特定类型关联的函数。

1、基本方法定义

package main

import "fmt"

// 定义 Person 结构体
type Person struct {
    FirstName string
    LastName  string
    Age       int
}

// 定义方法,接收者为 Person 结构体
func (p Person) PrintFullName() {
    fmt.Println("Full Name:", p.FirstName, p.LastName)
}

func main() {
    // 创建 Person 结构体实例
    person := Person{
        FirstName: "John",
        LastName:  "Doe",
        Age:       30,
    }

    // 调用结构体方法
    person.PrintFullName()
}

解释
在这个例子中,定义了一个 Person 结构体,并在其上定义了一个方法 PrintFullName。这个方法的接收者是 Person 结构体,通过在方法定义中使用 (p Person) 将方法与结构体关联起来。在 main 函数中创建了一个 Person 结构体实例,并调用了其方法 PrintFullName

2、方法中修改结构体字段

package main

import "fmt"

// 定义 Person 结构体
type Person struct {
    FirstName string
    LastName  string
    Age       int
}

// 定义方法,接收者为指向 Person 结构体的指针
func (p *Person) UpdateAge(newAge int) {
    p.Age = newAge
}

func main() {
    // 创建 Person 结构体实例
    person := Person{
        FirstName: "Alice",
        LastName:  "Smith",
        Age:       25,
    }

    // 调用结构体方法,更新 Age 字段
    fmt.Println("Before Update:", person)
    person.UpdateAge(30)
    fmt.Println("After Update:", person)
}

解释
在这个例子中,定义了一个 Person 结构体和一个方法 UpdateAge。这个方法的接收者是指向 Person 结构体的指针。通过在方法定义中使用 (p *Person),可以在方法内部修改结构体字段的值。在 main 函数中,创建一个 Person 结构体实例,并调用方法 UpdateAge 更新 Age 字段的值。

3、使用值接收者和指针接收者

package main

import "fmt"

// 定义 Rectangle 结构体
type Rectangle struct {
    Width  int
    Height int
}

// 定义方法,值接收者
func (r Rectangle) Area() int {
    return r.Width * r.Height
}

// 定义方法,指针接收者
func (r *Rectangle) Scale(factor int) {
    r.Width = r.Width * factor
    r.Height = r.Height * factor
}

func main() {
    // 创建 Rectangle 结构体实例
    rect := Rectangle{
        Width:  5,
        Height: 10,
    }

    // 使用值接收者调用方法
    area := rect.Area()
    fmt.Println("Area:", area)

    // 使用指针接收者调用方法
    rect.Scale(2)
    fmt.Println("After Scaling:", rect)
}

解释
在这个例子中,定义了一个 Rectangle 结构体,并在其上定义了两个方法:Area 使用值接收者计算面积,Scale 使用指针接收者按指定因子缩放矩形。在 main 函数中,创建了一个 Rectangle 结构体实例,并分别使用值接收者和指针接收者调用了方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风不归Alkaid

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值