golang的复合数据结构包括:数组、切片、结构体、函数、map、channel、接口等
1.数组
1.1数组的初始化
import "fmt"
func main() {
//数组的初始化1
var arr1 [3]int
arr1[0] = 1
arr1[1] = 2
arr1[2] = 3
fmt.Println(arr1)
//数组的初始化2
var arr2 = [4]int{1, 2, 3, 4}
fmt.Println(arr2)
//数组初始化3,自动判断数组长度
var arr3 = [...]int{1, 2}
fmt.Println(arr3)
//数组初始化4,指定下标
arr4 := [...]int{1: 1, 3: 5}
fmt.Println(arr4)
//数组的类型
var arr5 [3]int
var arr6 [4]string
fmt.Printf("%T,%T", arr5, arr6)
}
1.2 数组是值类型,赋值和传参会赋值整个数组,因此改变副本的值,不会改变本身的值
package main
import "fmt"
func main() {
var arr1 = [...]int{1, 2, 3}
arr2 := arr1
arr2[0] = 3
fmt.Println(arr1, arr2)
}
//[1 2 3] [3 2 3]
2.切片
在golang中,切片的定义和数组定义是相似的,但是需要注意的是,切片是引用数据类型
2.1 切片的引用
package main
import "fmt"
func main() {
var arr1 = []int{1, 2, 3}
arr2 := arr1
arr2[0] = 3
fmt.Println(arr1, arr2)
}
//[3 2 3] [3 2 3]
2.2 为什么要使用切片
切片(Slice)是一个拥有相同类型元素的可变长度的序列。它是基于数组类型做的一层封装。 它非常灵活,支持自动扩容。
切片是一个引用类型,它的内部结构包含地址、长度和容量。
package main
import "fmt"
func main() {
//切片的定义
var slice = []int{1, 2, 3}
fmt.Println(slice)
//数组定义切片
arr := [5]int{55, 56, 57, 58, 59}
a := arr[:]
b := arr[1:4]
c := arr[:3]
d := arr[3:]
fmt.Println(a)
fmt.Println(b)
fmt.Println(c)
fmt.Println(d)
}
2.3 切片的长度和容量
切片拥有自己的长度和容量,我们可以通过使用内置的len()函数求长度,使用内置的cap() 函数求切片的容量。
切片的长度就是它所包含的元素个数。
切片的容量是从它的第一个元素开始数,到其底层数组元素末尾的个数。切片s的长度和容量可通过表达式len(s)和cap(s)来获取。
import "fmt"
func main() {
// 长度和容量
arr1 := []int{1, 2, 3, 4, 5, 6}
fmt.Printf("长度%d 容量%d\n", len(arr1), cap(arr1))
arr2 := arr1[2:]
fmt.Printf("长度%d 容量%d\n", len(arr2), cap(arr2))
arr3 := arr1[2:4]
fmt.Printf("长度%d 容量%d\n", len(arr3), cap(arr3))
}
2.4 切片的本质
切片的本质就是对与数组的特殊封装,它包含了三个信息:
底层数组的指针
切片的长度
切片的容量
2.5 使用make函数创造切片
func main() {
// make()函数创建切片
var slices = make([]int, 4, 8)
//[0 0 0 0]
fmt.Println(slices)
// 长度:4, 容量8
fmt.Printf("长度:%d, 容量%d", len(slices), cap(slices))
}
2.6 golang中没办法通过下标来给切片扩容,如果需要扩容,需要用到append
package main
import "fmt"
func main() {
//切片的扩容
slices2 := []int{1, 2, 3, 4}
slices2 = append(slices2, 5)
fmt.Println(slices2)
// 输出结果 [1 2 3 4 5]
//切片的合并
// 合并切片
slices3 := []int{6, 7, 8}
slices2 = append(slices2, slices3...)
fmt.Println(slices2)
// 输出结果 [1 2 3 4 5 6 7 8]
//使用copy复制切片
//前面我们知道,切片就是引用数据类型
//值类型:改变变量副本的时候,不会改变变量本身
//引用类型:改变变量副本值的时候,会改变变量本身的值
//如果我们需要改变切片的值,同时又不想影响到原来的切片,那么就需要用到copy函数
// 需要复制的切片
var slices4 = []int{1, 2, 3, 4}
// 使用make函数创建一个切片
var slices5 = make([]int, len(slices4), len(slices4))
// 拷贝切片的值
copy(slices5, slices4)
// 修改切片
slices5[0] = 4
fmt.Println(slices4)
fmt.Println(slices5)
//[1 2 3 4]
//[4 2 3 4]
}
2.7 删除切片中的值
并没有删除切片元素的专用方法,我们可以利用切片本身的特性来删除元素
package main
import "fmt"
func main() {
//删除索引为1的元素
var slice = []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
slice = append(slice[:1], slice[2:]...)
fmt.Println(slice)
}
2.8 切片的排序
切片排序第一种就是使用排序算法
第二种就是自带的排序
package main
import (
"fmt"
"sort"
)
func main() {
var numslice4 = []int{3, 2, 1, 4, 5, 7, 6}
sort.Ints(numslice4)
fmt.Println(numslice4)
var slice5 = []int{9, 8, 4, 5, 1, 7}
sort.Sort(sort.Reverse(sort.IntSlice(slice5)))
}
3. map
map是一种无序的基于key-value的数据结构,Go语言中的map是引用类型,必须初始化才能使用。
3.1 map初始化
ap类型的变量默认初始值为nil
,需要使用make()
函数来分配内存。语法为:
make:用于slice、map和channel的初始化
package main
import "fmt"
func main() {
// 方式1初始化
var userInfo = make(map[string]string)
userInfo["name"] = "xiaohei"
userInfo["age"] = "20"
userInfo["sex"] = "男"
fmt.Println(userInfo)
fmt.Println(userInfo["userName"])
// 声明式初始化
var userInfo2 = map[string]string {
"name":"xiaohei",
"age":"20",
"sex":"男",
}
fmt.Println(userInfo2)
}
3.2 map的操作
//遍历map
for s, s2 := range userInfo {
fmt.Println("key:", s, " value:", s2)
}
//判断某个元素是否存在
value, ok := userInfo2["name"]
fmt.Println(value, ok)
//删除某个元素
delete(userInfo2, "sex")
fmt.Println(userInfo2)