10 结构
结构
- Go 中的struct与C中的struct非常类似,并且Go没有class
- 使用Type(Name) struct{}定义结构,名称遵循可见性规则
- 支持指向自身的指针类型成员
- 支持匿名结构,可用作成员或者定义成员变量
- 匿名结构也可以用于map的值
- 可以使用字面值对结构进行初始化
- 允许直接通过指针来读写结构成员
- 相同类型的成员可以直接拷贝赋值
- 支持== 与 != 比较运算符,但不支持>或<
- 支持匿名字段,本质是定义了以某个类型名为名称的字段
- 嵌入结构作为匿名字段看起来像继承,但不是继承
- 可以使用匿名字段指针
struct的简单使用
我们先定义一个struct,然后在main函数里面使用它即可
type test struct {
Name string
Age int
}
func main() {
a := test{}
a.Name = "Leo" // 对Name这个进行赋值
a.Age = 22 // 对Age这个变量进行赋值
a := test{ // 也可以这样进行简单初始化,初始化的格式如下:
Name: "Leo ", // 变量名: 值,
}
fmt.Println(a)
}
struct 多层嵌套
所谓的多层嵌套就是struct里面再包含了一个struct,代码如下所示:
type person struct {
Name string
Age int
contact struct { // struct里面再包含了一个struct
Phone, City string
}
}
func main() {
a := person{Name: "joe", Age: 19}
a.contact.Phone = "182165234545" // 给里面那层struct赋值的时候只能这样做
a.contact.City = "Beijing"
fmt.Println(a)
}
struct 内存地址的拷贝
package main
import (
"fmt"
)
type test struct {
Name string
Age int
}
func main() {
a := test{
Name: "Leo ",
}
a.Age = 22
A(a)
fmt.Println(a) // 此时打印出来的结果还是22
}
func A(per test) {
per.Age = 19
fmt.Println("A", per)
}
// 打印结果如下:
A {Leo 19} // 值已经发生改变
{Leo 22} // 值没有发生改变
从上面的例子能够看出来,这个函数A的修改并没有影响main方法里面的值,所以可以得出这个修改实际上是test的一个内存拷贝,如果真正想在A里面修改值后影响到 main里面的值,就需要把内存地址传给A,那么就应该这么做,代码如下:
func main() {
a := test{
Name: "Leo ",
}
a.Age = 22
A(&a) // 加上&符合把内存地址传入
fmt.Println(a)
}
func A(per *test) { // 加上一个*号在test之前
per.Age = 19
fmt.Println("A", per)
}
那么问题来了,如果我有多个方法需要传入内存地址,那么该如何一次性让a等于内存地址呢?请看下面的代码
func main() {
a := &test{ // 提前把&放入到test之前
Name: "Leo ",
}
a.Age = 22
A(a)
B(a)
fmt.Println(a)
}
func A(per *test) { // 每个方法 的test前面添加一个*即可
per.Age = 19
fmt.Println("A", per)
}
func B(per *test) { // 每个方法 的test前面添加一个*即可
per.Age = 90
fmt.Println("B", per)
}
struct 匿名结构
匿名结构 的写法和js的自执行函数差不多,go的写法是 struct{}{}
func main() {
a := struct {
Name string
Age int
}{
Name: "joe",
Age: 19,
}
fmt.Println(a)
}
匿名结构
struct里面没有写变量名,只写了类型,所以赋值的时候只能照着顺序来
type person struct {
string
int
}
func main() {
a := person{"joe", 19}
fmt.Println(a)
}
struct 比较
两个struct之间比较的话,struct名字必须一样,如下所示
func main() {
a := person{"joe", 19}
b := person{"joe", 22}
fmt.Println(a == b) // 两个struct的名字一样才行
}
在struct继承情况下,如果有同名的变量会发生什么情况
话不多说,直接看代码:
import (
"fmt"
)
type human struct {
student
Name string
}
type student struct {
Name string
}
func main() {
b := human{Name: "hehe", student: student{Name: "Leo"}} // 变量同名了
fmt.Println(b.Name, b.student.Name)
}
// 打印结果
hehe Leo
由打印结果为导向,可以看出来,即使在继承struct的情况,有同名的也不会互相影响。
在struct继承情况下,父类没有的变量名而子类有会发生什么情况
话不多说,请看代码
import (
"fmt"
)
type human struct {
student
}
type student struct {
Name string
}
func main() {
b := human{student{Name: "Leo"}}
fmt.Println(b.Name, b.student.Name)
}
// 打印结果
Leo Leo
由打印结果为导向,可以看出来,如果父struct没有name的话,那么就会从子struct上取值
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构