文章目录
- 一、数组
- 数组的定义
- 数组声明
- 数组特点
- 数组元素修改
- 二、切片
- 切片声明
- 基于数组创建切片
- 使用make()函数构造切片
- 使用append()为切片动态添加元素\
- 使用copy()复制新的切片
- 数组与切片相互转换
- 三、Map映射
- Map定义
- 使用make()函数创建map
- 用切片作为map的值
- 使用delete()函数删除元素
一、数组
数组的定义
一个由固定长度的特定元素组成的序列
数组声明
标准格式声明数组:
var variable_name [size]type
初始化数组:
var variable_name = [size]type{value,...}
编译器自行推断数组大小:
var variable_name = [...]type {value,...}
一些示例:
//示例1
var a [3] int //声明一个数组为 a ,类型为int,大小为3的数组
a[0] = 12 //为第一个元素填充数据,为12
a[1] = 13 //为第二个元素填充数据,为13
a[2] = 14 //为第三个元素填充数据,为14
//示例2
var a = [3] int {12,13,14} //定义且声明数组内容
//示例3
a := [3]int {12,13,14}//定义且声明数组内容
//示例4
a := [3]int{12}//可以只填充部分数据
//示例5
a := [3]int {1:13,2:14}//填充指定位置
//示例6
a := [...]int{12,13,14}//编译器自行判断数组长度
数组特点
- 数组的每个元素可以通过索引下标来访问
- 索引下标的范围从0开始到数据长度减1结束
- 数组无法灵活扩容:在定义数组元素数量后,赋值元素变量个数必须要小于或者等于预设值的元素数量
- type指任意的基本类型,也可以是数组本身,实现多维数组
- 在Go语言中数组是值类型而不是引用类型
- 这意味着当数组变量被赋值时,将会获得原数组的拷贝,新数组中元素的改变不会影响原数组中元素的值
示例:
package main
import "fmt"
func main() {
a := [...]int{12, 78, 50}
b := a // 将a数组复制给b数组
b[0] = 60
fmt.Println(a)
fmt.Println(b)
}
//运行结果为:
//[12 78 50]
//[60 78 50]
数组元素修改
package main
import "fmt"
func main() {
var a [1]string //定义一个1个元素的string类型数组,string默认值为空
var b = [2]string{“a”, “b”} //定义一个2个元素的string类型数组
c := [3]string{"a", "b", "c"} //定义并初始化一个3个空间的string类型数组
d := [...]string{"a", "b", "c", "d"} //自动推到元素个数
e := d //拷贝数组
e[0] = "e" //修改数组指定位置的值
fmt.Println(a, len(a)) //打印a数组、a数组长度
fmt.Println(b)
fmt.Println(c)
fmt.Println(d, len(d))
fmt.Println(e, len(e))
}
//运行结果为:
//[] 1
//[a b]
//[a b c]
//[a b c d] 4
//[e b c d] 4
二、切片
数组和切片的对比
切片声明
切片声明:
var name[]type = []type{......}
切片特点:
- []中不需要指定长度,即长度是不固定的
- 可以追加元素,在追加时可能使切片的容量增大,可以从数据中生成新的切片或者是声明新的切片
示例:
package main
import "fmt"
func main() {
var a []int= []int{10,11,12,13}
fmt.Println(a,len(a))
}
//运行结果为:
//[10 11 12 13] 4
基于数组创建切片
var name [] type = 数组名[开始位置:结束位置]
特点:
- 结束位置的元素不取
- 切片数量 = 结束位置下标 - 开始位置下标
- 当缺省开始位置时,表示从连续的区域开头到结束位置
在编程和数据处理领域,"缺省"(或“默认”)通常指的是在没有明确指定某个值或选项时,系统或程序将自动采用的一个预设值或行为。这个预设值或行为被称为“缺省值”或“默认值”。
- 当缺省结束位置时,表示从开始位置到整个连续区域末尾
- 两者同时缺省时,与数组本身等效
- 两者同时为0时,等于空切片,一般用于切片复位
示例:
//示例1
package main
import "fmt"
func main() {
a := [5]string{"A","B","C","D"}
var b []string = a[1:2]
fmt.Println(a)
fmt.Println(b,len(b))
}
//运行结果为:
//[A B C D ]
//[B] 1
//示例2
package main
import "fmt"
func main() {
a := [5]int{76, 77, 78, 79, 80}
var b []int = a[1:3] //取a数组的第1到第3个元素
var c []int = a[:3] //取a数组的第0到第3个元素
var d []int = a[1:] //取a数组的第1到最后一个元素
var e []int = a[:] //取a数组的第0到最后一个元素
var f []int = a[0:0] //空切片
fmt.Println(a,len(a))
fmt.Println(b,len(b))
fmt.Println(c,len(c))
fmt.Println(d,len(d))
fmt.Println(e,len(e))
fmt.Println(f,len(f))
}
//运行结果为:
//[76 77 78 79 80] 5
//[77 78] 2
//[76 77 78] 3
//[77 78 79 80] 4
//[76 77 78 79 80] 5
//[] 0
- 切片本身不包含任何数据
- 切片是底层数组的一个上层表示
- 对切片进行的任何修改都将反映在底层数据化中
package main
import "fmt"
func main() {
a := [5]string{"A","B","C","D","E"}
var b []string = a[1:3]
fmt.Println("修改前的a数组:",a)
fmt.Println("修改前的b切片:",b)
b[1]="2"
fmt.Println("修改后的a数组:",a)
fmt.Println("修改后的b切片:",b)
}
//运行结果为:
//修改前的a数组: [A B C D E]
//修改前的b切片: [B C]
//修改后的a数组: [A B 2 D E]
//修改后的b切片: [B 2]
- 切片的长度是指切片中元素的个数
- 切片的容量是指从切片的起始元素开始到其底层数组中的最后一个元素的个数
- 切片的长度可以动态的改变(最大为其容量)
- 任何超出最大容量的操作都会发生运行时错误
package main
import (
"fmt"
)
func main() {
a := [...]string{"A", "B", "C", "D", "E"}
b := a[1:3]
fmt.Printf("数组a长度为:%d \n切片b容量为:%d", len(a), cap(b))
}
//运行结果为:
//数组a长度为:5
//切片b容量为:4
使用make()函数构造切片
var name [] type = make([]type,size,cap)
特点:
- type指切片元素类型
- size 指的是为这个类型分配多少个元素
- cap 为预分配的元素数量
- cap设定后不会影响 size,只是为了提前分配空间,降低多次分配空间造成的性能问题
package main
import "fmt"
func main() {
var a [] int =make([]int,5,10)
//创建一个切片,初始元素个数为5,并预留10个元素的存储空间
a[0]=10
a[4]=14
fmt.Println("切片内容:", a)
fmt.Println("切片长度:", len(a))
fmt.Println("切片容量:", cap(a))
}
//运行结果为:
//切片内容: [10 0 0 0 14]
//切片长度: 5
//切片容量: 10
使用append()为切片动态添加元素\
append(name,value)
append(name,[]type[value,value,value]...)
特点:
- 可以为切片追加单个或多个元素;或者是追加切片
- 使用append()函数为切片动态添加元素时,如果空间不足以容纳足够多的元素,切片就会进行“扩容”,此时新切片的长度会发生改变。
- 扩展容量小于1024个元素时按当前切片的容量(Cap)2倍扩容,扩展容量大于1024个元素时按Cap的1/4扩容。
package main
import“fmt”
func main() {
a := []int{10, 20, 30, 40, 50}
b := a[1:3]
fmt.Println(a)
fmt.Println(b)
b = append(b, 60)
fmt.Printf(“第一次追加后,切片a为:%d 切片a容量为:%d\n", a, cap(a))
fmt.Printf(“第一次追加后,切片b为:%d 切片b容量为:%d\n", b, cap(b))
b = append(b, 70,80,90,100)
fmt.Printf(“第二次追加后,切片a为:%d 切片a容量为:%d\n", a, cap(a))
fmt.Printf(“第二次追加后,切片b为:%d 切片b容量为:%d\n", b, cap(b))
}
//运行结果为:
//[10 20 30 40 50]
//[20 30]
//第一次追加后,切片a为:[10 20 30 60 50] 切片a容量为:5
//第一次追加后,切片b为:[20 30 60] 切片b容量为:4
//第二次追加后,切片a为:[10 20 30 60 50] 切片a容量为:5
//第二次追加后,切片b为:[20 30 60 70 80 90 100] 切片b容量为:8
在对切片 b 进行第一次 append 时,由于它仍然指向 a 的底层数组,因此 a 和 b 共享数据;但第二次 append 超出容量时,切片 b 就会分配新的底层数组,不再共享 a 的数据。
使用copy()复制新的切片
copy(destSlice,srcSlice)
特点:
- destSlice 为复制的目标切片
- srcSlice 为数据来源切片
- 目标切片必须分配过空间且足够承载复制的元素个数,并且来源和目标的类型必须一致。
- copy() 函数来源切片和目标切片可以共享同一个底层数组,甚至有重叠也没有问题。
package main
import "fmt"
func main() {
a := []int{0,1,2,3,4,5}
b := []int{10,11,12}
fmt.Println(a)
fmt.Println(b)
copy(b,a) // 只会复制a的前3个元素到b中
fmt.Println(a)
fmt.Println(b)
}
//运行结果为:
//[0 1 2 3 4 5]
//[10 11 12]
//[0 1 2 3 4 5]
//[0 1 2]
数组与切片相互转换
- 需要使用[:]将数组伪装为切片类型后再进行赋值,否则无法通过编译
- 数组与切片中的元素类型必须相同
切片转成数组:
package main
import "fmt"
func main() {
//切片转成数组
s := []int{10, 11, 12}
var a [3]int
fmt.Println(copy(a[:], s))
fmt.Println(a)
}
//运行结果为:
//3
//[10 11 12]
数组转成切片:
package main
import "fmt"
func main() {
//数组转成切片
a := [...]int{10, 11, 12}
b := make([]int, 3)
fmt.Println(copy(b, a[:]))
fmt.Println(b)
}
//运行结果为:
//3
//[10 11 12]
三、Map映射
Map定义
一种无序的Key/value的集合
能够通过key值快速检索数据值
map这种数据结构在其他编程语言中也称为字典、映射或哈希表。
Golang的map由两种重要的结构构成:hmap和bmap
声明map集合:
var name map[key_type]value_type
语法说明如下:
- name为map变量名
- key_type为键类型
- value_type为键值对应值类型
package main
import "fmt"
func main() {
a:=map[int]string{
110:"报警电话",
120:"急救电话",
119:"消防电话"}
fmt.Println(a)
}
//运行结果为:
//map[110:报警电话 119:消防电话 120:急救电话]
使用make()函数创建map
make(map[KeyType]ValueType, [cap])
特点:
- map可以在声明的时候填充元素,也可以单独填充元素
- map中的数据都是成对出现的
- map类型的变量默认初始值为nil
- 其中cap表示map的容量,该参数虽然不是必须的,但是我们应该在初始化map的时候就为其指定一个合适的容量。
用切片作为map的值
//示例1
package main
import "fmt"
func main() {
a := make(map[string]int,10)
a["报警电话"] = 110;
a["急救电话"] = 120;
a["火警电话"] = 119;
fmt.Println(a)
}
//运行结果为:
//map[急救电话:120 报警电话:110 火警电话:119]
//示例2
package main
import "fmt"
func main() {
//map的值为切片:
a := make(map[int][]string, 2)// 创建一个容量为 2 的 map,键为 int,值为 []string(切片)
a[1] = make([]string, 0, 2) // 为键 1 初始化一个长度为 0、容量为 2 的切片
a[1] = append(a[1], "A", "a") // 向切片中追加元素 "A" 和 "a"
fmt.Println(a)
}
//运行结果为:
//map[1:[A a]]
//示例3
package main
import "fmt"
func main() {
//切片的元素类型为map:
b := make([]map[string]int, 2)
b[0] = make(map[string]int, 2)
b[0]["A"] = 1
b[0]["a"] = 2
fmt.Println(b)
}
//运行结果为:
//[map[A:1 a:2] map[]]
使用delete()函数删除元素
delete(map,key)
特点:
- 如果要删除的key不存在,那么这个调用将什么都不发生,也不会有什么副作用
- 但是如果传入的map变量的值是nil,该调用将导致程序抛出异常(panic)
示例
package main
import "fmt"
func main() {
a:=map[int]string{
110:"报警电话",
120:"急救电话",
119:"消防电话"}
delete(a,110)
fmt.Println(a)
}
//运行结果为:
//map[119:消防电话 120:急救电话]