slice
特性
- slice 是一个引用类型
-
从底层来说,slice 是一个struct结构体
具体类型如下
type slice struct{ ptr *[2]int len int cap int }
- 内存分布
使用方式
- 通过切片引用数组
-
通过 make 创建 slice
-
直接指定具体数组
var slice []int = []int{1,2,4}
方式一:数组事先存在,程序员可见
方式二:make创建数组并创建切片,数组由底层维护,不可见
注意事项
- slice 初始化时仍不能越界,但可以append
-
切片可以继续切片
-
append 底层原理
- append 的本质就是对数组扩容
- go 底层会重新创建一个新的数组(按照扩容后的大小)
- 将slice 原来包含的元素拷贝到新数组中
- slice 重新引用到新数组
- 新数组仍由底层维护,对外不可见
- 通过 copy 方法得到的 slice ,数据空间独立,不相互影响
map
声明
-
var 变量名 map[keyType]valueType
-
keyType 不能为 slice、func、map等无法比较的类型
-
声明是不会分配内存的,初始化需要使用 make,之后才能使用
-
map1 := make(map[string]map[string]string) map1["stu01"] = make(map[string]string) map1["stu01"]["name"] = "jake" map1["stu01"]["sex"] = "man" map1["stu01"]["address"] = "beijing" fmt.Println(map1)
增删改查
-
删除
delete(map,key)
key不存在也不会报错重新指向变量可一次性全部删除
- 查询
val,ok := map1["stu01"] if ok { fmt.Printf("有stu01,值为%v",val) }else { fmt.Println("无此key") }
map的遍历
map 无法使用单纯的for进行遍历
实现map的有序遍历
map2 := make(map[int]int) map2[10] = 100 map2[1] = 10 map2[50] = 112013 map2[42] = 10123 map2[123] = 23100 map2[5] = 110 fmt.Println(map2) var keys []int for index, value := range map2 { keys = append(keys, index) fmt.Printf("%v=======%v\n", index, value) } fmt.Println("####################################") sort.Ints(keys) for _, data := range keys { fmt.Printf("%v=====%v\n", data, map2[data]) }
注意
- map 是引用类型
-
map的容量能动态增长,并且是二倍增长
-
map的value经常使用struct类型,更适合管理复杂的数据
结构体
概述:不同类型数据组合的有机整体
格式:type strName struct { … }
指针有合法指向后,才操作成员 (new、普通指针)
作为函数参数是为值传递
结构体与结构体变量
结构体是一种数据类型
结构体变量是结构体的是实例
内存布局
注意事项
- 结构体的字段在内存中是连续分布的
- struct 上的字段可以加一个 tag,该 tag 可通过反射机制获取,用于序列化与反序列化
接口(interface)
定义但不实现的一组方法集
说明:
- 接口里的所有方法都没有方法体,即未实现。体现了多态和高内聚低耦合的思想
- 实现接口只需要实现接口内的所有方法,即 Go中没有implement 关键字
- 只要是自定义数据类型都可以实现接口
- 接口中不能存在变量
- 一个接口可以继承多个别的接口
- 接口类型默认是一个指针(引用类型)
接口和继承
-
接口的价值在于,设计好各种规范
-
继承的价值在于解决代码的复用性和可维护性
-
接口比继承更加灵活