golang学习四:[复合类型]数组, 切片, map, 结构体

一、复合类型:

1. 分类:

类型名称长度默认值说明
pointer指针nil
array数组0
slice切片nil引用类型
struct结构体

2. 数组的定义和使用:

数组 是指一系列同一类型的数据集合;

2.1 数组的定义:

var 数组名 [长度]类型

数组定义完之后没有赋值, 默认输出是0;

2.2 数组赋值:

  • 使用下标赋值;
  • 注意下标越界;
var arr [5] int
arr[0] = 1
arr[1] = 2
arr[2] = 3
arr[3] = 4
arr[4] = 5

2.3 匿名变量打印:

func main() {
	var arr [10]int
	for i := 0; i < 10; i++ {
		arr[i] = i + 1
	}

	for index, ele := range arr {
		fmt.Println(index, ele)
		// 0 1
		// 1 2
		// 2 3
		// 3 4
		// 4 5
		// 5 6
		// 6 7
		// 7 8
		// 8 9
		// 9 10
	}
}

2.4 数组初始化:

全部初始化:
var a [5]int = [5]int{1, 2, 3, 4, 5}

// 自动推导
b := [5]int{1, 2, 3, 4, 5}
部分初始化:
c := [5]int{1,2,3}
// c = [1, 2, 3, 0, 0]
指定索引初始化:
d := [5]int{2: 10, 4: 20}
// d = [0, 0, 10, 0, 20]
自动推导长度:
f := [...]int{1,2,3}
// len(f) = 3

2.5 数据类型:

arr := [5]int{1,2,3,4,5}
fmt.Printf("%T\n", arr)		// [5]int
  • 数组名表示整个数组;
  • 数组名对应的地址就是数组第一个元素对应的地址;

2.6 数组的逆置:

arr[i], arr[j] = arr[j], arr[i]

2.7 冒泡排序:

3. 随机数:

import (
	"fmt"
	"math/rand"
	"time"
)

func main() {
	// 1. 导入头文件: math/rand
	// 2. 随机数种子;
	// 3. 创建随机数

	rand.Seed(time.Now().UnixNano())
	fmt.Println(rand.Int())
	fmt.Println(rand.Intn(10)) // 生成10以内的随机数
}

4. 数组作为函数参数:

func BubbleSort(arr [10]int) [10]int {
	for i := 0; i < len(arr)-1; i++ {
		for j := 0; j < len(arr)-1-i; j++ {
			if arr[j] < arr[j+1] {
				arr[j], arr[j+1] = arr[j+1], arr[j]
			}
		}
	}
	return arr
}

func main() {
	// 数组作为函数参数是"值传递"
	arr := [10]int{9, 5, 3, 1, 4, 5, 8, 6, 10, 8}
	arr = BubbleSort(arr)
	fmt.Println(arr)
}

5. 二维数组:

var arr [3][4] int	// 定义3x4的二维数组
// [[0 0 0 0] 
//	[0 0 0 0] 
//	[0 0 0 0]]

// 全部初始化
arr1 := [3][4]int{{1,2,3,4}, {5,6,7,8}, {9,10,11,12}}
// [[1 2 3 4] [5 6 7 8] [9 10 11 12]]

// 部分初始化
arr2 := [3][4]int{{1, 2, 3, 4}, {5, 6, 7}}
// [[1 2 3 4] [5 6 7 0] [0 0 0 0]]

6. 切片定义和使用:

6.1 定义

// 定义方式1
var slice []int // 定义空切片	[]
fmt.Println(slice)
fmt.Println(len(slice)) // 长度
fmt.Println(cap(slice)) // 容量

// 定义方式2
s1 := []int{1, 2, 3}
fmt.Println(s1)

// 定义方式3: 使用make函数时, 长度值要小于容量值; 容量值可省略
s2 := make([]int, 5, 10) // 定义切片, 长度是5, 容量是10
s2 = append(s2, 1, 2, 3, 4, 5, 6)
fmt.Println(s2)	// [0 0 0 0 0 1 2 3 4 5 6]

6.2 使用:

使用参考数组的使用

6.3 切片地址和扩容:

  • 在使用append追加数据时, 长度超过容量, 容量会自动扩容;
  • 一般新容量是旧容量的2倍, 如果超过1024字节, 每次扩容旧容量的四分之一;

6.4 切片的截取:

  • 截取后的切片是原切片的一部分, 修改截取后的切片, 原切片也被修改;
s3 := []int{10, 20, 30, 40, 50, 60}
// 截取 s[low: high: max]
// len = high - low
// cap = max - low
s4 := s3[0:3:5]
fmt.Println(s4) // [10 20 30]
fmt.Println(len(s4))	// 3
fmt.Println(cap(s4))	// 5

6.5 切片的拷贝:

切片拷贝: copy

  • 是深拷贝;
  • 使用copy进行拷贝, 在内存中存储两个独立的切片内容(内存地址不同)
var s []int = []int{1,2,3,4,5}

s1 := make([]int, 5)
fmt.Println(s1)	// [0,0,0,0,0]
copy(s1, s)
fmt.Println(s1)	// [1,2,3,4,5]

6.6 切片作为函数参数:

  • 切片传参, 传的是地址, 指向同一个地址;
  • 使用append修改切片参数, 切片地址可能发生改变;

7.map 字典结构:

7.1 map的定义和使用:

  • map不能使用cap, 查看容量, 但是可以指定容量;
// 定义1
var 变量名 map[键类型]值类型
var m2 map[int]string

// 定义2
变量名 := make(map[键类型]值类型, 容量)
m2 := make(map[int]string, 容量)
  • 键是唯一的, 值是可以重复的;
  • map是无序结构
m2[1] = "张三"
m2[2] = "李四"
m2[3] = "王五"
m2[4] = "张三"

初始化:

m3 := map[int]string{1: "张三", 2: "李四", 3: "王五", 4: "张三"}
func main() {
	var m1 map[int]string
	fmt.Printf("%p\n", m1)	// 0x0
}
  • 当内存地址打印为0x0时, 为系统占用, 不允许用户做读写操作;

7.2 map的键值:

  • map的键必须支持逻辑运算, 一般建议使用基本类型, 即: 不能使用引用类型变量做key
m2 := make(map[string][3]int)

m2["小明"] = [3]int{97, 98, 99}
m2["小亮"] = [3]int{80, 81, 82}
m2["小红"] = [3]int{100, 101, 102}

fmt.Println(m2)	// map[小亮:[80 81 82] 小明:[97 98 99] 小红:[100 101 102]]

for k, v := range m2 {
	fmt.Println(k, v)
	// 小明 [97 98 99]
	// 小亮 [80 81 82]
	// 小红 [100 101 102]
}

删除:

delete(map变量, key值)

7.3 map作为函数参数:

  • map传参, 传的是地址(或 引用)

8. 结构体:

8.1 结构的定义和使用

  • 结构体定义在main函数外
package main

import "fmt"

type 结构体名 struct {
	// 结构体成员列表
	// 成员名 数据类型
}

// 定义结构体
type Student struct {
	id   int
	name string
	sex  string
	age  int
	addr string
}

func main() {
	// 顺序初始化, 每个成员必须初始化
	var s1 Student = Student{1, "小明", "男", 18, "北京市"}
	fmt.Println(s1) // {1 小明 男 18 北京市}

	// 自动化推导
	s2 := Student{name: "小亮", age: 18, sex: "女", id: 2, addr: "朝阳区"}
	fmt.Println(s2) // {2 小亮 女 18 朝阳区}

	// 定义结构体变量 符合类型
	// var 变量名 结构体
	var s3 Student
	// 赋值
	s3.id = 3
	s3.name = "小红"
	s3.sex = "女"
	fmt.Println(s3) // {3 小红 女 0 }	不赋值, 就是类型的默认值
}
// 结构体的地址就是第一个属性的地址
// 结构体所占内存的大小就是所有属性占内存的和
fmt.Printf("%p\n", &s3)      // 0xc0000b20c0
fmt.Printf("%p\n", &s3.id)   // 0xc0000b20c0
fmt.Printf("%p\n", &s3.name) // 0xc0000b20c8
fmt.Printf("%p\n", &s3.sex)	// 0xc0000b20d8
  • 结构体可以做恒等比较;

8.2 结构体数组和切片:

  • 结构体数组作为函数参数, 是值传递;
  • 结构体切片作为函数参数, 是地址(引用)传递;

8.3 结构体和map:

8.4 结构体作为函数参数:

  • 结构体作为函数参数, 是值传递;
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浅弋、璃鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值