介绍
Go 语言中数组可以存储同一类型的数据,但在结构体中我们可以为不同项定义不同的数据类型。结构体是由一系列具有相同类型或不同类型的数据构成的数据集合。
结构体是值类型
定义结构体
字段可以是 基本数据类型、数组、引用数据类型
字段类型默认值:指针、slice、map的零值都是nil,即还没有分配空间
type 结构体名称 struct {
field1 type
field2 type
...
}
使用
package main
import "fmt"
func main() {
// 定义结构体
type Cat struct {
Name string
Age int
Color string
}
// 使用
var cat1 Cat // 像使用其它变量一样
cat1.Name = "小白"
cat1.Age = 3
cat1.Color = "白色"
fmt.Println("cat1 = ", cat1) // {小白 3 白色}
}
结构体和结构体变量的区别和联系
- 结构体是自定义的数据类型,代表一类事物。 Cat
结构体变量(实例)是具体的,实际的,代表一个具体变量。 cat1
内存探究
引用类型字段使用注意
指针、slice、map的零值都是nil
- slice、map类型的字段,使用赋值的时候要先make,分配内存空间
- 不同结构体变量的字段是独立的,互不影响。(结构体是值类型) ```bash package main
import “fmt”
// 字段类型默认值:指针、slice、map的零值都是nil,即还没有分配空间 type Person struct { Name string Age int Score float64 Ptr *int Slice []int Map map[string]string }
type Monster struct { Name string Age int }
func main() {
var p1 Person
fmt.Println(“p1 = “, p1) // { 0 0
// p1.Slice[0] = 100 // panic: runtime error: index out of range [0] with length 0
// 使用Slice、Map 先 make
p1.Slice = make([]int, 5) // slice需要指定长度(容量)
fmt.Println(“make后 p1 = “, p1)
p1.Slice[0] = 100
p1.Map = make(map[string]string) // map会自动增长,不需要指定长度和容量
p1.Map[“hobby”] = “coding”
fmt.Println(“p1 = “, p1) // { 0 0
// 不同结构体变量的字段互不影响 var monster1 Monster monster1.Name = “小牛” monster1.Age = 2 monster2 := monster1 // 值拷贝,互不影响 monster2.Name = “小马” fmt.Println(“monster1 = “, monster1) // {小牛 2} fmt.Println(“monster2 = “, monster2) // {小马 2} }
<a name="pdHGW"></a>
## 结构体变量内存
![image.png](https://cdn.nlark.com/yuque/0/2021/png/2932776/1637582464340-9b1efae7-2294-4dc2-a8a8-158e6a9bde84.png#clientId=ub26924f9-cccc-4&from=paste&id=u0a2aafbb&originHeight=300&originWidth=1126&originalType=binary&ratio=1&rotation=0&showTitle=false&size=194870&status=done&style=shadow&taskId=uddb10aac-c85f-4bb6-a761-2a0b4280e6c&title=)
<a name="DNGwh"></a>
# 结构体变量4种定义方式
- new 用来分配内存,主要用来**分配值类型**,比如 int, float32, struct... **返回的是指针**。
- make 用来分配内存,主要用来分配**引用类型**,比如 chan, map, slice
结构体指针
```bash
package main
import "fmt"
type Person struct {
Name string
Age int
}
func main() {
// 结构体变量定义方式
// 方式1
var p1 Person
fmt.Println("p1 = ", p1)
// 方式2
// var p2 = Person{}
// var p2 = Person{"tom", 10} // 这种方式要严格按照定义字段的顺序,否则类型推导报错
var p2 = Person{
Name: "tom",
Age: 20,
}
fmt.Println("p2 = ", p2)
// 方式3
var p3 *Person = new(Person)
// 指针结构体变量,标准赋值方式
(*p3).Name = "abc" // 这个写法不方便
// (*p3).Name = "abc" 等价于 p3.Name = "abc"
// go 底层会做指针取值处理
p3.Age = 3
fmt.Println("p3 = ", *p3)
// 方式4
var p4 *Person = &Person{}
(*p4).Name = "hhh"
p4.Age = 5
fmt.Println("p4 = ", p4)
}