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)
}
相关推荐
蒙娜丽宁2 天前
Go语言错误处理详解
ios·golang·go·xcode·go1.19
qq_172805592 天前
GO Govaluate
开发语言·后端·golang·go
littleschemer3 天前
Go缓存系统
缓存·go·cache·bigcache
程序者王大川4 天前
【GO开发】MacOS上搭建GO的基础环境-Hello World
开发语言·后端·macos·golang·go
Grassto4 天前
Gitlab 中几种不同的认证机制(Access Tokens,SSH Keys,Deploy Tokens,Deploy Keys)
go·ssh·gitlab·ci
高兴的才哥5 天前
kubevpn 教程
kubernetes·go·开发工具·telepresence·bridge to k8s
少林码僧5 天前
sqlx1.3.4版本的问题
go
蒙娜丽宁5 天前
Go语言结构体和元组全面解析
开发语言·后端·golang·go
蒙娜丽宁6 天前
深入解析Go语言的类型方法、接口与反射
java·开发语言·golang·go
三里清风_6 天前
Docker概述
运维·docker·容器·go