「Golang成长之路」内建容器
一、数组(Array)
数组:数组是指有序的元素序列。如果将有限个类型相同的变量的集合命名,那么这个名称就是数组名,而组成数组的各个变量称为数组的分量,也称为数组的元素,有时也称为下标变量,而数组中的数据可以使用下标(索引)来查找到。
其实在编程语言中数组的概念是一样的,下面具体来看看golang中数组是如何定义和使用的:
1.数组的定义
方法一:
var arr1 [5]int //定义一个拥有5个元素的数组,此时元素全为0
方法二:
arr2 := [5]int{0, 1, 2, 3, 4} //定义并放入值
方法三:
arr3 := [...]int{0, 1, 2, 3, 4} //用[...],此时不需写入数组空间具体是多少
二维数组的定义:
package main import "mft" func main { //二维数组 var arr4 [4][5]int fmt.Println(arr4) }
输出为:
[[0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0]]
2.数组的使用
- 遍历
输出为:package main import "fmt" arr :=[...]int{0, 1, 2, 3, 4} for i := range arr{ fmt.Println(arr[i]) }
也可以这样遍历:0 1 2 3 4
输出为://.数组的遍历 for i,v := range arr3{ //i为对应元素的索引值,v为元素值 fmt.Println(i, v) }
0 0 1 1 2 2 3 3 4 4
- 改变元素的值
输出为:arr :=[...]int{0, 1, 2, 3, 4} arr[0] = 100 //将arr[0]改为100 fmt.Println(arr) arr[0] = 0 //将arr[0]改回0 fmt.Println(arr)
[100 1 2 3 4 ] [0 1 2 3 4 ]
数组的值传递
数组的值传递仍然是将整个数组copy一份传入函数,不会改变arr的值//数组的值传递 package main import "fmt" //定义函数: func printarr1(arr [5]int){ arr[0] = 100 fmt.Println(arr) } func main(){ printarr1(arr) fmt.Println(arr) }
输出为:
[0 1 2 3 4 ]
使用指针
使用指针是将数组的相应值的地址传入函数//使用指针 package main import "fmt" //定义函数: func printarr2(arr *[5]int) { arr[0] = 100 fmt.Println(arr) } func main(){ printarr2(&arr3) fmt.Println(arr3) }
输出为:
[100 1 2 3 4]
二、切片(Slice)
切片是golang中重要操作之一
直接看操作:
package main
import main
func main(){
//切片
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
s := arr[2:6]
fmt.Println("s = ",s)
fmt.Println("arr[2:6 =",arr[2:6])
fmt.Println("arr[:6] = ",arr[:6])
fmt.Println("arr[2:] = ",arr[2:])
fmt.Println("arr[:] = ",arr[:])
}
输出为:
s = [2 3 4 5]
arr[2:6 = [2 3 4 5]
arr[:6] = [0 1 2 3 4 5]
arr[2:] = [2 3 4 5 6 7]
arr[:] = [0 1 2 3 4 5 6 7]
- Slice值的改变
改变Slice中元素的值,会导致底层arr值的改变
输出为:package main import m="fmt" //定义函数,改变Slice的值 //切片 func updateSlice(s []int){ s[0] = 100 } //主函数 func main(){ arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7} s1 :=arr[2:] s2 := arr[:] //改变之前 fmt.Println(s1) fmt.Println(s2) fmt.Println("change after:") //函数调用 updateSlice(s1) fmt.Println(s1) //最后底层的arr的值也会随之改变 fmt.Println(arr) }
现在我们再来改变S2:[2 3 4 5 6 7] [0 1 2 3 4 5 6 7] change after: [100 3 4 5 6 7] [0 1 100 3 4 5 6 7]
输出为:fmt.Println(s2) updateSlice(s2) fmt.Println(s2) fmt.Print(arr)
[0 1 100 3 4 5 6 7] [100 1 100 3 4 5 6 7] [100 1 100 3 4 5 6 7]
这里还有一种情况:Slice的更新
package main
import "fmt"
func main(){
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
s2 := arr[:]
//Slice中值的更新
//对Slice的操作,其实是对底层arr的修改
fmt.Println(s2)
s2 = s2[:5]
fmt.Println(s2)
s2 = s2[2:]
fmt.Println(s2)
fmt.Println(arr)
输出为:
[0 1 2 3 4 5 6 7]
[0 1 2 3 4]
[2 3 4]
[0 1 2 3 4 5 6 7]
- Slice的扩展
先来看一个例子:
现在肯定对这段代码有疑问吧!//Slice的扩展 package main import "fmt" func main(){ arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7} fmt.Println("Extneding Slice:") fmt.Println(arr) s1 = arr[2:6] s2 = s1[3:5] fmt.Println(s1) fmt.Println(s2) fmt.Println(arr) }
s2 = s1[3:5]
会不会报错?
答案:不会!
下面来看看运行结果:[0 1 2 3 4 5 6 7] [2 3 4 5] [5 6] [0 1 2 3 4 5 6 7]
*原因:在golang中Slice是可是往后扩展的,例如上面
arr := […]int{0, 1, 2, 3, 4, 5, 6, 7}
s1 = arr[2:6] = [2 3 4 5]
s2 = s1[3:5],此时已经超出s1的范围了,但是Slice是对底层arr的操作,并且可以往后扩展的,所以往底层走就应该是[5 6],s2 = s1[3:5] = [5 6] *
向slice添加元素
向slice添加元素使用append(s, x)
//向slice添加元素 arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7} //切分 s1 :=arr[2:] s2 := arr[:] //打印 fmt.Println(s1) fmt.Println(s2) //添加元素 s3 := append(s2, 10) s4 := append(s3, 11) s5 := append(s4, 12) fmt.Println("s3, s4, s5 =",s3, s4, s5) fmt.Println("arr = ",arr)
输出为:
[2 3 4 5 6 7] [0 1 2 3 4 5 6 7] s3, s4, s5 = [0 1 2 3 4 5 6 7 10] [0 1 2 3 4 5 6 7 10 11] [0 1 2 3 4 5 6 7 10 11 12] arr = [0 1 2 3 4 5 6 7] //arr的容量已经固定,不会变
slice的建立
- 1
package mian import "fmt" //定义函数 func printslice(s []int){ fmt.Printf(" s=%v, len=%d, cap=%d",s, len(s), cap(s)) } func main(){ var s []int //s的初始化,生成100个奇数 for i:=0; i < 100; i++{ printslice(s) fmt.Print("\n") s = append(s, 2*i + 1) } }
- 2
输出为:package main import "fmt" //定义函数 func printslice(s []int){ fmt.Printf(" s=%v, len=%d, cap=%d",s, len(s), cap(s)) } func main(){ //graet slice s1 := []int{0,1,2} s2 := make([]int, 16) s3 := make([]int, 10, 32) //调用函数 printslice(s1) printslice(s2) printslice(s3) }
s=[0 1 2], len=3, cap=3 s=[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0], len=16, cap=16 s=[0 0 0 0 0 0 0 0 0 0], len=10, cap=32
- copy Slice
//copy slice copy(s2, s1) //将s1的内容copy到s2上 fmt.Println(s2)
- delete Slice
删除操作
输出为:package main import "fmt" 定义函数 func printslice(s []int){ fmt.Printf(" s=%v, len=%d, cap=%d",s, len(s), cap(s)) } //主函数 func main(){ //delete "2" s5 := []int{0, 1, 2, 3, 4, 5, 6, 7} s5 = append(s5[:2], s5[3:]...) //使用切片(Slice) printslice(s5) //delete front s5 = s5[1:] printslice(s5) //delete tail s5 = s5[:len(s5)-1] printslice(s5)
s=[0 1 3 4 5 6 7], len=7, cap=8 s=[1 3 4 5 6 7], len=6, cap=7 s=[1 3 4 5 6], len=5, cap=7
三、映射(Map)
map:是一个无序,key—value对,不会出现某个key对应不同的value
map的定义:
//定义map m := map[string]string{ //[string]对应key,string对应value "name":"yangkuang", "work":"students", "year": "20", } m3 := map[string]int{ "a": 0, "b": 1, "c": 2, //空map的定义 m1 := make(map[string]int) // empty map1 var m2 map[string]int fmt.Println(m, m1, m2) //map2 == nil
输出为:
map[name:yangkuang work:students year:21] map[] map[]
- map的遍历
输出为:for k, v := range m3{ fmt.Println(k, v) }
a 0 b 1 c 2
- map的查找
func main(){ //定义map m := map[string]string{ "name":"yangkuang", "work":"students", "year": "21", } iname, ok := m["name"] //key—name存在则将key对应的value赋值给iname,并且将ok赋值为true,否则ok为false fmt.Println(iname,ok) //输出:yangkuang true }
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: