struct 类型

Go 语言中,也和 C 或者其他语言相同,可以声明新的类型,作为其它类型的属性或字段的容器。

例如,我们可以创建一个自定义类型 TreeNode 代表一个树的实体。 这个实体拥有属性:值,左节点和右节点。

这样的类型我们称之 struct。如下代码所示:

Go 复制代码
type TreeNode struct {
    Val   int
    Left  *TreeNode
    Right *TreeNode
}

如何使用 struct 呢?

Go 复制代码
var node TreeNode // node 现在就是 TreeNode 类型的变量了

node.Val = 1
node.Left = nil
node.Right = nil
fmt.Println(node, reflect.TypeOf(node)) // {1 <nil> <nil>} main.TreeNode

node1 := TreeNode{2, nil, nil}
fmt.Println(node1, reflect.TypeOf(node1)) // {2 <nil> <nil>} main.TreeNode

node2 := TreeNode{Val: 3, Left: nil, Right: nil}
fmt.Println(node2, reflect.TypeOf(node2)) // {3 <nil> <nil>} main.TreeNode

node3 := new(TreeNode)
node3.Val = 4
node.Left = nil
node.Right = nil
fmt.Println(node3, reflect.TypeOf(node3)) // &{4 <nil> <nil>} *main.TreeNode

struct匿名字段

Go 支持只提供类型,而不写字段名的方式,也就是匿名字段,也称为嵌入字段。

当匿名字段是一个 struct 的时候,那么这个 struct 所拥有的全部字段都被隐式地引入了当前定义的这个 struct

Go 复制代码
package main

import "fmt"

type Human struct {
    name   string
    age    int
    weight int
}

type Student struct {
    Human      // 匿名字段,那么默认 Student 就包含了 Human 的所有字段
    speciality string
}

func main() {
    // 初始化一个学生
    mark := Student{Human{"Mark", 25, 120}, "Computer Science"}

    // 访问相应的字段
    fmt.Println("His name is ", mark.name)
    fmt.Println("His age is ", mark.age)
    fmt.Println("His weight is ", mark.weight)
    fmt.Println("His speciality is ", mark.speciality)
    // 修改对应的备注信息
    mark.speciality = "AI"
    fmt.Println("Mark changed his speciality")
    fmt.Println("His speciality is ", mark.speciality)
    // 修改年龄信息
    fmt.Println("Mark become old")
    mark.age = 46
    fmt.Println("His age is", mark.age)
    // 修改体重信息
    fmt.Println("Mark is not an athlet anymore")
    mark.weight += 60
    fmt.Println("His weight is", mark.weight)
}

Student 访问属性 agename 的时候,就像访问自己所有用的字段一样,对,匿名字段就是这样,能够实现字段的继承。

student 还能访问 Human 这个字段作为字段名。

mark.Human.age -= 1

通过匿名访问和修改字段相当的有用,但是不仅仅是 struct 字段,所有的内置类型和自定义类型都是可以作为匿名字段使用。

go 复制代码
type Student struct {
    Human  // 匿名字段,struct
    Skills // 匿名字段,自定义的类型 string slice
    int    // 内置类型作为匿名字段
    speciality string
}

// 修改匿名内置类型字段
jane.int = 3
fmt.Println("Her preferred number is", jane.int)

例子可以得到 struct 不仅仅能够将 struct 作为匿名字段,自定义类型、内置类型都可以作为匿名字段,而且可以在相应的字段上面进行函数操作。

如果 human 里面有一个字段叫做 phone,而 student 也有一个字段叫做 phone,那么该怎么办呢?

Go 里面很简单的解决了这个问题,最外层的优先访问,也就是当你通过 student.phone 访问的时候,是访问 student 里面的字段,而不是 human 里面的字段。

这样就允许我们去重载通过匿名字段继承的一些字段,当然如果我们想访问重载后对应匿名类型里面的字段,可以通过匿名字段名来访问。

go 复制代码
package main

import "fmt"

type Human struct {
    name string
    age int
    phone string  // Human 类型拥有的字段
}

type Employee struct {
    Human  // 匿名字段 Human
    speciality string
    phone string  // 雇员的 phone 字段
}

func main() {
    Bob := Employee{Human{"Bob", 34, "777-444-XXXX"}, "Designer", "333-222"}
    fmt.Println("Bob's work phone is:", Bob.phone)
    // 如果我们要访问 Human 的 phone 字段
    fmt.Println("Bob's personal phone is:", Bob.Human.phone)
}
相关推荐
研究司马懿4 小时前
【云原生】Gateway API高级功能
云原生·go·gateway·k8s·gateway api
梦想很大很大18 小时前
使用 Go + Gin + Fx 构建工程化后端服务模板(gin-app 实践)
前端·后端·go
lekami_兰1 天前
MySQL 长事务:藏在业务里的性能 “隐形杀手”
数据库·mysql·go·长事务
却尘1 天前
一篇小白也能看懂的 Go 字符串拼接 & Builder & cap 全家桶
后端·go
ん贤1 天前
一次批量删除引发的死锁,最终我选择不加锁
数据库·安全·go·死锁
mtngt112 天前
AI DDD重构实践
go
Grassto3 天前
12 go.sum 是如何保证依赖安全的?校验机制源码解析
安全·golang·go·哈希算法·go module
Grassto5 天前
11 Go Module 缓存机制详解
开发语言·缓存·golang·go·go module
程序设计实验室6 天前
2025年的最后一天,分享我使用go语言开发的电子书转换工具网站
go
我的golang之路果然有问题6 天前
使用 Hugo + GitHub Pages + PaperMod 主题 + Obsidian 搭建开发博客
golang·go·github·博客·个人开发·个人博客·hugo