golang简明入门进阶指南02数组切片map类型的基础使用(代码片段)

如何在5年薪百万 如何在5年薪百万     2022-12-11     222

关键词:

五、集合类型

5.1 数组

数据定义

func defArray() 
	//定义数组,默认赋值0
	var arr1 [5]int
	fmt.Println("init val of arr1 =",arr1)
	arr1=[5] int 1,3,4,5
	fmt.Println(arr1)

	//定义数组并赋予初始值
	var arr2 = [3]int1, 3, 4
	arr3 := [3]int13, 3, 4
	fmt.Println(arr2, arr3)
	// 定义二位数组
	arr4 := [3][4]int1, 2, 3, 4, 2, 4, 5, 5, 3, 4, 5, 4
	fmt.Println(arr4)

	//不固定长度数组
	arr5 := [...]int1, 3, 4
	fmt.Println(arr5)

数据遍历

下划线可以用来你做参数占位,省略参数

func printArray() 

	arr := [3]int13, 3, 4
	for i := range arr 
		fmt.Println(arr[i])
	

	fmt.Println("---------------")
	//打印index,value
	for i, v := range arr 
		fmt.Println(i, v)
	
	fmt.Println("---------------")
	//打印value,_用于省略变量
	for _, v := range arr 
		fmt.Println(v)
	
	fmt.Println("---------------")
	//不常用,for循环便利

	for i := 0; i < len(arr); i++ 
		fmt.Println(arr[i])
	



数组值传递(go特殊)

  1. 数组是一种值类型,调用func f(arr[10] int)会拷贝数组
  2. 不同长度的数组是不同类型,长度3的数组不能接收长度2的数组。
  3. 数值也是值传递,需通过指针实现引用传递
//1.只能接受长度为3的数组
//2. 值传递而非引用长度
func valTransferArray(arr [3]int) 

	arr[0] = 10
	fmt.Println(arr)


//1.只能接受长度为3的数组
//2. 值传递而非引用长度
func pointerArray(arr *[3]int) 

	arr[0] = 10
	fmt.Println(arr)


func main() 
	arr := [3]int3, 4, 5
	valTransferArray(arr)
	//数组时值传递,所以数组并没有改变
	fmt.Printf("after %s", arr)

	pointerArray(&arr)
	fmt.Printf("afterpointer %s", arr)



使用指针可以实现引用传递

[10 4 5]
after [%!s(int=3) %!s(int=4) %!s(int=5)]&[10 4 5]
afterpointer [%!s(int=10) %!s(int=4) %!s(int=5)]

5.2 动态数组·切片 slice

slice和array很相似,但使用时有巨大差异

slice定义

  • 可以通过slice=nil判断是否为空切片
  • 不指定cap时,默认cap=len
func defSlice()  
	//定义slice
	var s1 [] int
	fmt.Println(&s1)
	fmt.Println(s1==nil) //true ,可以用nil判断slice是否是空的
	fmt.Printf("len= %d  val=%v \\n",len(s1),s1)

	//定义slice并赋初值,
	s2:=[]int1,3,4
	fmt.Printf("s2 leng=%d cap=%d val=%v \\n",len(s2),cap(s2),s2)

	//定义slice并开辟空间(type,leng,cap),但不赋值
	s3:=make([]int,3,5)
	fmt.Printf("s3 leng=%d cap=%d val=%v \\n",len(s3),cap(s3),s3)

切片切割

func sliceArray() 
	//半开半闭区间,包括开始,不包括结尾
	arr := [...]int2, 3, 4, 5, 6, 7, 8, 9
	fmt.Println(arr[2:4])
	fmt.Println(arr[:4])
	fmt.Println(arr[4:])

切片扩展

func appendSlice()
	s1:=make([]int,3,5)
	fmt.Printf("s1 leng=%d cap=%d val=%v \\n",len(s1),cap(s1),s1)
	s1=append(s1,1)
	fmt.Printf("s1 leng=%d cap=%d val=%v \\n",len(s1),cap(s1),s1)
	s1=append(s1,2)
	fmt.Printf("s1 leng=%d cap=%d val=%v \\n",len(s1),cap(s1),s1)

	//超出slice的cap时,会按照2*cap自动扩容
	s1=append(s1,3)
	fmt.Printf("s1 leng=%d cap=%d val=%v \\n",len(s1),cap(s1),s1)


	s2:=append(s1,3,4)
	fmt.Printf("s2 leng=%d cap=%d val=%v \\n",len(s2),cap(s2),s2)



增删改查

func testSlice2() 
	s2 := []int23, 4, 3, 5
	s3 := make([]int, 10, 32)

	//复制slice
	copy(s3, s2)
	printSlice(s2)
	printSlice(s3)

	//删除第N个元素
	s2 = append(s2[:1], s2[2:]...)
	printSlice(s2)

	//

slice和array关系

slice是数组的切片,对array的视图和引用,slice使用引用传递
注:slice是array的一个视图,本身没有数据

通过slice可以引用传递改变数组

	arr := [...]int1, 3, 43
	sliceTranArray(arr[:])
	fmt.Println("after", arr)

//使用slice传递数组
func sliceTranArray(array []int) 
	array[0] = 100
	fmt.Println(array)


切片原理(重要)

切片是array的视图,包含了三部分

  1. ptr切片的起点引用
  2. 切片长度
  3. cap扩展区域
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7f5CakVx-1648100093923)(E:/youdao/微信截图_20211128215021.png)]
func reSlice() 
	arr := [...]int0,1, 2, 3, 4, 5, 6, 7
	s1 := arr[2:6]
	s2 := s1[3:5]
	fmt.Println(s1)
	fmt.Println(s2)



结果

[2 3 4 5]
# s1指向的是arr的引用,引用中包含扩展区
# s2指向的也是arr的引用,3,5获取了扩展区内容
[5 6]

如果想slice添加的元素超过了cap的上线,系统就会创建新的数组,将原来的数组就会垃圾回收掉。

slice扩容机制


func printSlice(slice []int) 
	//打印slice的实际长度和扩展长度
	fmt.Println(len(slice), cap(slice))


func testSlice() 


	var s1 = []int //zero value is nil
	for i := 0; i < 100; i++ 

		s1 = append(s1, 2*i+1)
		printSlice(s1)
	

	printSlice(s1)



slice达到16后是指数扩容的


1 1
2 2
3 4
4 4
5 8
6 8
7 8
8 8
9 16
10 16
11 16
12 16
13 16
。。。
60 64
61 64
62 64
63 64
64 64
65 128
66 128
67 128
。。。
100 128

Process finished with the exit code 0

5.3 Map(key-value)类型

  • map的key是无序的,可以通过slice转换排序
  • map使用hash表,key必须可以hash
  • slice,map,function以外的类型都可以作为key。自定义类型包括三者之一不能作为key

map定义

空map的长度都是0,map本身=nil可以判断map不包含元素

//方式1:仅声明一个map,map[key-type]value-type,但不赋值
	//tip:可以通过nil判断map是否包含元素
	var map1 map[string]string
	fmt.Println("map1==nil ",map1==nil)

	//方式2:make方式声明map,并制定初始size
	map2:=make(map[int]string,1)

	fmt.Println("size before",len(map2),map2) //0
	map2[0]="java"
	map2[1]="golang"
	map2[2]="python"
	fmt.Println("size after",len(map2),map2) //3

	//方式3:声明map同时赋初值
	map3:=map[string]string
		"name":     "zhangsan",
		"location": "shagnhai",
	
	fmt.Println(map3)


	//定义并赋值
	m := map[string]string
		"name":     "zhangsan",
		"location": "shagnhai",
	
	fmt.Println(m)

增删改查

使用for遍历,结果无序

	//key是无需的,hashmap结构
	for k, v := range m ß
		fmt.Println(k, v)
	

通过m[key]获取元素,可以通过下面方法判断是否存在

	fmt.Println(m["name"])
	//如果key不存在获取到zerovalue(这里是空字符串)
	fmt.Println(m["nameddd"])
	if s, ok := m["name"]; ok 
		fmt.Println(s)
	 else 
		fmt.Println("key not exist")
	

delete(key) 删除元素
key不存在,删除无效,不报错

//删除元素
	fmt.Println("delete----")
	delete(m, "name")
	fmt.Println(m)

修改map内容,map作为参数可以理解为引用传递


//修改map
changeVal(m)
fmt.Println(m)
//map是引用传递,而非值传递
func changeVal(maptmp map[string]string)

	maptmp["New"]="new member"


完整代码

func crudMap()  

	//定义并赋值
	m := map[string]string
		"name":     "zhangsan",
		"location": "shagnhai",
	
	fmt.Println(m)


	//遍历:key是无需的,hashmap结构
	for k, v := range m 
		fmt.Println(k, v)
	

	//打印单个元素
	fmt.Println(m["name"])
	//如果key不存在获取到zerovalue(这里是空字符串)
	fmt.Println(m["nameddd"])
	if s, ok := m["nameddd"]; ok 
		fmt.Println(s)
	 else 
		fmt.Println("key not exist")
	

	//删除元素
	fmt.Println("delete----")
	delete(m, "nme")
	fmt.Println(m)


	//修改map
	changeVal(m)
	fmt.Println(m)


5.4 rune

  • rune相当于golang的char类型
  • utf8.RunecountInString获取字符数
func runeTest() 

	str := "Yes,我爱中国!"  //utf-8编码,英语1个byte,汉子3bytes
	fmt.Println(len(str))
	for i, b := range []byte(str) 
		//长度为17位,等于len结果
		fmt.Printf(" (%d, %X) ", i, b)
	

	fmt.Println("------------ch-------")
	for i, ch := range str 
		fmt.Printf(" (%d, %X) ", i, ch)
	

	fmt.Println("-------------rune array")
	for i, r := range []rune(str) 
		fmt.Printf(" (%d, %X) ", i, r)
	


结果
str转换成rune数组后,可以得到业务上的含义。这个过程是内部创建一个rune数组后转换的结果

17
 (0, 59)  (1, 65)  (2, 73)  (3, 2C)  (4, E6)  (5, 88)  (6, 91)  (7, E7)  (8, 88)  (9, B1)  (10, E4)  (11, B8)  (12, AD)  (13, E5)  (14, 9B)  (15, BD)  (16, 21) ------------ch-------
 (0, 59)  (1, 65)  (2, 73)  (3, 2C)  (4, 6211)  (7, 7231)  (10, 4E2D)  (13, 56FD)  (16, 21) -------------rune
 (0, 59)  (1, 65)  (2, 73)  (3, 2C)  (4, 6211)  (5, 7231)  (6, 4E2D)  (7, 56FD)  (8, 21) 

golang简明入门进阶指南01golang基础变量函数条件控制(代码片段)

说明本文目的:学习golang必须掌握的基本语法和概念前置条件:搭建号golang环境并输出helloworld一、变量和常量这部分要分清golang语言的优势特性1.1变量声明名称在前,类型在后,重点突出变量声明既有初值,... 查看详情

golang基础——map数组切片存放不同类型的数据(代码片段)

基础知识,不解释,直接看代码packagemainimport( "fmt")typeUserstruct IDstring Namestring Ageintfuncmain() fmt.Println("-------------------map-------------------------") data:=map[st 查看详情

golang基础——map数组切片存放不同类型的数据(代码片段)

基础知识,不解释,直接看代码packagemainimport( "fmt")typeUserstruct IDstring Namestring Ageintfuncmain() fmt.Println("-------------------map-------------------------") data:=map[st 查看详情

go数组切片映射的原理--简明解析

数组、切片、映射是Golang的最重要的数据结构,下面是对这3种数据结构的一点个人总结:一、数组数组是切片和映射的基础数据结构。数组是一个长度固定的数据类型,存储着一段具有相同数据类型元素的连续内存块。因为数... 查看详情

golang:map的定义操作排序以及map切片(代码片段)

map概述golang中的引用类型。与其他语言中的map类型基本相似,都是k-v形式的,k不可重复,元素是无序的,并且支持扩容。基本语法var变量名map[keytype]valuetypekey可以是很多类型bool、数字、string、指针、channel,... 查看详情

golang:map的定义操作排序以及map切片(代码片段)

map概述golang中的引用类型。与其他语言中的map类型基本相似,都是k-v形式的,k不可重复,元素是无序的,并且支持扩容。基本语法var变量名map[keytype]valuetypekey可以是很多类型bool、数字、string、指针、channel,... 查看详情

golang入门:切片(slice)(代码片段)

切片(slice)是Golang中一种比较特殊的数据结构,这种数据结构更便于使用和管理数据集合。切片是围绕动态数组的概念构建的,可以按需自动增长和缩小。切片的动态增长是通过内置函数append()来实现的,这个函数可以快速且高效... 查看详情

golang复合类型(代码片段)

前言上文Golang基本类型中我们介绍了golang基本类型的常见用法,本文将介绍golang中的复合数据类型,常用的复合数据类型有array数组,slice切片,map字典和struct四种。文章目录前言数组Sliceslice基本操作初始化在slice... 查看详情

golang基础——切片和数组的区别(代码片段)

切片和数组的区别:● 切片是指针类型,数组是值类型● 数组的长度是固定的,而切片不是(切片是动态的数组)● 切片比数组多一个属性:容量(cap)● 切片的底层是数组切片是指针类型࿰... 查看详情

golang基础——切片和数组的区别(代码片段)

切片和数组的区别:● 切片是指针类型,数组是值类型● 数组的长度是固定的,而切片不是(切片是动态的数组)● 切片比数组多一个属性:容量(cap)● 切片的底层是数组切片是指针类型࿰... 查看详情

golang入门:切片(slice)(代码片段)

切片(slice)是Golang中一种比较特殊的数据结构,这种数据结构更便于使用和管理数据集合。切片是围绕动态数组的概念构建的,可以按需自动增长和缩小。切片的动态增长是通过内置函数append()来实现的,这个函数可以快速且高效... 查看详情

golang学习之路—map切片(代码片段)

map切片基本介绍案例演示基本介绍切片的数据类型如果是map,则我们称为sliceofmap,map切片,这样使用则map个数就可以动态变化了。案例演示要求:使用一个map来记录学生的信息name和age,即一个学生对应一个map,并且... 查看详情

golang数组与切片(代码片段)

golang中坑的慢慢踩!我们都知道golang中的切片是引用类型,但是在函数中使用append给切片追加元素是行不通的,需要使用切片的指针类型才能增加元素数组的使用:packagemainimport("fmt")funcChangeArr(arr[5]int)arr[0]=6funcChangeArr2(arr*[5]int)ar... 查看详情

golang之切片

1.切片:切片是数组的一个引用,因此切片是引用类型2.切片的长度可以改变,因此,切片是个可变的数组。3.切片遍历方式和数组一样,可以用len()求长度4.cap可以求出slice最大的容量,0<=cap(slice) <=len(array),其中array... 查看详情

golang:map的定义操作排序以及map切片(代码片段)

map概述golang中的引用类型。与其他语言中的map类型基本相似,都是k-v形式的,k不可重复,元素是无序的,并且支持扩容。基本语法var变量名map[keytype]valuetypekey可以是很多类型bool、数字、string、指针、channel,... 查看详情

Golang 不能用作类型结构数组或切片文字

】Golang不能用作类型结构数组或切片文字【英文标题】:Golangcannotuseastypestructarrayorsliceliteral【发布时间】:2017-05-1203:51:52【问题描述】:我正在尝试在Go中编写一个函数,该函数采用带有目录URL的JSON并执行BFS以在该目录中查找... 查看详情

golang的简明安装指南

...开源项目都是基于go来做的,比如codis,ethereum等都用到了golang,所以免不了要使用这个东东,本文将简明介绍安装步骤以及环境变量的设置。下载http://www.woaipu.com/shops/zuzhuan/61406http://www.znds.com/tv-967956-1-1.htmlhttp:// 查看详情

golang数组和切片(代码片段)

数组的使用注意事项和细节1.数组是多个相同类型数据的结合,一个数组一旦声明/定义了,其长度是固定的,不能动态变化。2.vararr[]int这时arr就是一个slice切片,切片后面专门讲解。3.数组中的元素可以是任何数... 查看详情