go的数组、结构体
87 次阅读
一、数组(Array)
1. 数组核心特性
- 长度固定,声明时必须指定长度,长度属于数组类型的一部分
- 值类型,赋值、传参时会完整拷贝一份数据
- 下标从 0 开始访问元素,下标越界直接编译/运行报错
- 支持
len()获取数组长度
2. 数组声明与初始化
package main
import "fmt"
func main() {
// 1. 仅声明,使用类型默认零值填充
var arr1 [3]int
fmt.Println(arr1) // [0 0 0]
// 2. 声明同时赋值
var arr2 [3]int = [3]int{10, 20, 30}
fmt.Println(arr2)
// 3. 类型推导简写
arr3 := [3]string{"Go", "Java", "Python"}
// 4. 自动推导长度 ...
arr4 := [...]int{1, 2, 3, 4, 5}
fmt.Println(len(arr4)) // 5
// 5. 指定下标初始化,未赋值元素填零值
arr5 := [5]int{1: 99, 3: 66}
fmt.Println(arr5) // [0 99 0 66 0]
}
3. 数组元素读写
func main() {
arr := [3]int{1, 2, 3}
// 读取
fmt.Println(arr[0])
// 修改
arr[1] = 99
fmt.Println(arr) // [1 99 3]
}
4. 数组遍历
方式1:普通for循环
arr := [3]int{10, 20, 30}
for i := 0; i < len(arr); i++ {
fmt.Printf("下标:%d,值:%d\n", i, arr[i])
}
方式2:range 遍历
arr := [3]int{10, 20, 30}
for idx, val := range arr {
fmt.Println(idx, val)
}
// 只取值,丢弃下标
for _, val := range arr {
fmt.Println(val)
}
5. 数组是值类型(拷贝特性)
数组赋值会完整复制,修改副本不会影响原数组
func main() {
a := [2]int{1, 2}
b := a
b[0] = 99
fmt.Println(a) // [1 2] 原数组不变
fmt.Println(b) // [99 2]
}
如需修改原数组,使用数组指针传参/赋值。
6. 多维数组
func main() {
// 二维数组:2行3列
var twoArr [2][3]int
twoArr[0][0] = 10
// 初始化
arr := [2][3]int{
{1, 2, 3},
{4, 5, 6},
}
fmt.Println(arr[1][2]) // 6
}
二、结构体(struct)
1. 结构体作用
自定义复合数据类型,把多个不同类型变量封装在一起,Go 实现面向对象的基础。
2. 结构体定义语法
type 结构体名 struct {
字段名1 类型1
字段名2 类型2
...
}
示例:
type Student struct {
name string
age int
score float64
}
3. 结构体实例化 4 种方式
package main
import "fmt"
type Student struct {
name string
age int
score float64
}
func main() {
// 方式1:按字段顺序赋值
s1 := Student{"小明", 18, 92.5}
// 方式2:指定字段名赋值(推荐,顺序无关)
s2 := Student{
name: "小红",
score: 96,
age: 17,
}
// 方式3:仅声明,字段填充零值
var s3 Student
fmt.Println(s3) // { 0 0}
// 方式4:结构体指针
s4 := &Student{"小李", 19, 88}
fmt.Println(s4.name) // 指针可直接点访问字段,自动解引用
}
4. 结构体字段读写
func main() {
var s Student
// 赋值
s.name = "小张"
s.age = 20
// 读取
fmt.Println(s.name, s.age)
}
5. 结构体是值类型
赋值、传参时整体拷贝,副本修改不影响原数据
func main() {
s1 := Student{"张三", 18, 90}
s2 := s1
s2.name = "李四"
fmt.Println(s1.name) // 张三,原数据不变
}
6. 结构体指针(修改原数据)
func modifyStu(s *Student) {
s.age = 99
}
func main() {
s := Student{"测试", 16, 80}
modifyStu(&s)
fmt.Println(s.age) // 99,原结构体被修改
}
7. 结构体嵌套
7.1 普通嵌套
type Address struct {
city string
addr string
}
type User struct {
name string
addr Address
}
func main() {
u := User{
name: "老王",
addr: Address{
city: "太原",
addr: "XX街道",
},
}
fmt.Println(u.addr.city)
}
7.2 匿名嵌套(提升字段,直接访问)
type Address struct {
city string
}
type User struct {
name string
Address // 匿名结构体,无字段名
}
func main() {
u := User{
name: "老李",
Address: Address{
city: "大同",
},
}
fmt.Println(u.city) // 可直接访问Address的city字段
}
8. 结构体方法(绑定函数)
给结构体添加方法,区分值接收者、指针接收者
type Student struct {
name string
age int
}
// 值接收者:拷贝副本,无法修改原结构体
func (s Student) Show() {
fmt.Printf("姓名:%s,年龄:%d\n", s.name, s.age)
}
// 指针接收者:操作原结构体
func (s *Student) SetAge(newAge int) {
s.age = newAge
}
func main() {
s := Student{"小明", 16}
s.Show()
s.SetAge(17)
s.Show()
}
9. 结构体可见性规则
结构体、结构体字段首字母大写:其他包可访问;小写仅当前包可见。
// 其他包可访问
type User struct {
Name string // 大写导出
age int // 小写私有,外部包无法读取
}
三、数组 vs 结构体 核心区别
| 特性 | 数组 Array | 结构体 struct |
|---|---|---|
| 存储数据 | 同类型一组元素 | 多个不同类型字段 |
| 长度 | 固定不可变 | 无长度概念,字段固定 |
| 访问方式 | 数字下标 arr[0] |
字段名 stu.name |
| 适用场景 | 批量同类型数据 | 封装实体对象(用户、订单等) |
| 类型特征 | 长度是类型一部分 [3]int 和 [5]int 是两种类型 |
自定义独立类型 |