Golang--数组、切片、映射

时间:2024-11-05 11:39:11

1、数组

1.1 数组类型

var 数组名 [数组大小]数据类型 

package main
import "fmt"

func main(){
	//1、定义一个数组
	var arr1 [5]int
	arr1[0] = 100
	arr1[1] = 200
	fmt.Println(arr1) //[100 200 0 0 0]
}

1.2 数组的初始化方式

package main
import "fmt"
func main(){
        //第一种:
        var arr1 [3]int = [3]int{3,6,9} //指定类型
        fmt.Println(arr1)
        //第二种:
        var arr2 = [3]int{1,4,7} //自动类型推导
        fmt.Println(arr2)
        //第三种:
        var arr3 = [...]int{4,5,6,7} //自动类型推导
        fmt.Println(arr3)
        //第四种:
        var arr4 = [...]int{2:66,0:33,1:99,3:88} //指定下标初始化+自动类型推导
        fmt.Println(arr4)
}



注意:

  • 定义数组时,声明的长度不同,即使元素的数据类型相同,但整体的数组类型也是不同的,即长度也是属于类型的一部分
  • Go中数组属值类型,在默认情况下是值传递,因此会进行值拷贝,即形参不影响实参
  • 如想在其它函数中,去修改原来的数组,可以使用引用传递(指针方式)
    package main
    import "fmt"
    
    func f(arr *[]int){
    	for i := 0; i < len(*arr); i++ {
    		(*arr)[i] += 10
    	}
    }
    
    func main(){
    	var arr []int = []int{1,2,3,4,5,6,7,8,9,0}
    	f(&arr)
    	fmt.Println(arr) //[11 12 13 14 15 16 17 18 19 10]
    }

1.3 数组内存

package main
import "fmt"
func main(){
        //声明数组:
        var arr [3]int16
        //获取数组的长度:
        fmt.Println(len(arr))
        //打印数组:
        fmt.Println(arr)//[0 0 0]
        //证明arr中存储的是地址值:
        fmt.Printf("arr的地址为:%p",&arr)
        //第一个空间的地址:
        fmt.Printf("arr的地址为:%p",&arr[0])
        //第二个空间的地址:
        fmt.Printf("arr的地址为:%p",&arr[1])
        //第三个空间的地址:
        fmt.Printf("arr的地址为:%p",&arr[2])
}

注意:数组每个空间占用的字节数取决于数组类型
数组优点:可以通过[]下标进行线性访问

1.4 数组遍历

1、使用普通for循环

2、使用for-range循环 (key - value)

package main
import "fmt"

func main(){
	var arr1 = [...]int{1,2,3,4,5,6,7,8,9,10}
	//普通for循环遍历
	for i := 0; i < len(arr1); i++{
		arr1[i] += 10
		fmt.Println(arr1[i]) //11 12 13 14 15 16 17 18 19 20
	}
	fmt.Println("")
	//for-range遍历
	for k,v := range arr1{
		v += 10 //v只是一个副本,对v的修改不会影响arr1的元素
		fmt.Println(arr1[k]) //11 12 13 14 15 16 17 18 19 20
	}
	fmt.Println("")
}

注意:使用for-range时,接收的value变量只是一个副本,副本改变不影响原来arr1数组的元素

 

1.5 二维数组/多维数组

定义:

package main
import "fmt"

func main(){
	//定义二维数组
	var arr [3][4]int = [3][4]int{{1,2,3,4},{5,6,7,8},{9,10,11,12}}
	//遍历二维数组
	for i := 0; i < len(arr); i++ {
		for j := 0; j < len(arr[i]); j++ {
			fmt.Printf("%d ",arr[i][j]) //1 2 3 4 5 6 7 8 9 10 11 12
		}
	}
	fmt.Println("")
	//定义多维数组
	var arr2 [3][2][2][2]int = [3][2][2][2]int{{{{1,2},{3,4}},{{5,6},{7,8}}},{{{9,10},{11,12}},{{13,14},{15,16}}},{{{17,18},{19,20}},{{21,22},{23,24}}}}
	//遍历多维数组
	for i := 0; i < len(arr2); i++ {
		for j := 0; j < len(arr2[i]); j++ {
			for k := 0; k < len(arr2[i][j]); k++ {
				for l := 0; l < len(arr2[i][j][k]); l++ {
					fmt.Printf("%d ",arr2[i][j][k][l]) //1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
				}
			}
		}
	}
}
package main
import "fmt"

func main(){
	//定义二维数组
	var arr [3][4]int = [3][4]int{{1,2,3,4},{5,6,7,8},{9,10,11,12}}
	//遍历二维数组
	for k1,v1 := range arr{
		for k2,v2 := range v1{
			fmt.Printf("arr[%v][%v] = %v\n",k1,k2,v2)
		}
	}
	//定义多维数组
	var arr2 [2][2][2][2]int = [2][2][2][2]int{{{{1,2},{3,4}},{{5,6},{7,8}}},{{{9,10},{11,12}},{{13,14},{15,16}}}}
	//遍历多维数组
	for k1,v1 := range arr2{
		for k2,v2 := range v1{
			for k3,v3 := range v2{
				fmt.Printf("arr2[%v][%v][%v] = %v\n",k1,k2,k3,v3)
			}
		}
	}
}

 

2、切片

2.1 切片

  • 切片(slice)是golang中一种特有的数据类型
  • 数组有特定的用处,但数组长度固定不可变,所以在 Go 语言的代码里并不是特别常见。相对的切片却是随处可见的,切片是一种建立在数组类型之上的抽象,它构建在数组之上并且提供更强大的能力和便捷。
  • 切片(slice)是对数组一个连续片段的引用,所以切片是一个引用类型。这个片段可以是整个数组,或者是由起始和终止索引标识的一些项的子集。需要注意的是,终止索引标识的项不包括在切片内。切片提供了一个相关数组的动态窗口。

切片的语法:
var 切片名 []类型 = 数组的一个片段引用

2.2  切片的内存分析

切片有3个字段的数据:

  • 一个是指向底层数组的指针
  • 一个是切片的长度
  • 一个是切片的容量

 

2.3 切片的定义

方式1:定义一个切片,然后让切片去引用一个已经创建好的数组
方式2:通过make内置函数来创建切片。基本语法: var切片名[type = make([], len,[cap])
(make底层创建一个数组,对外不可见,所以不可以直接操作这个数组,要通过slice去间接的访问各个元素,不可以直接对数组进行维护/操作)
方式3:定一个切片,直接就指定具体数组,使用原理类似make的方式。

注意:
切片定义后不可以直接使用,需要让其引用到一个数组,或者make一个空间供切片来使用
不能越界

package main
import "fmt"

func main(){
	//方式一:定义一个切片,然后让切片去引用一个已经创建好的数组。
	var arr [5]int = [5]int{1,2,3,4,5}
	var slice []int
	slice = arr[1:3]
	fmt.Println(slice)
	//方式二:通过make内置函数来创建切片。基本语法: var切片名[type = make([], len,[cap])
	// make函数的三个参数:1、切片类型;2、切片的长度;3、切片的容量。
	slice1 := make([]int, 5, 10)
	fmt.Println(slice1)
	fmt.Println(slice1[6])
	//方式三:定义一个切片,直接就指定具体数组。使用原理类似make的方式。
	slice2 := []int{1,2,3,4,5}
	fmt.Println(slice2)
}

 简写方式:

var slice = arr[0:end]  ----> var slice = arr[:end]                //从起始到指定位置

var slice = arr[start:len(arr)]  ---->  var slice = arr[start:]   //从指定位置到末尾

var slice = arr[0:len(arr)]   ----> var slice = arr[:]               //从起始位置到末尾位置

可以对切片继续切片:

package main
import "fmt"

func main(){
	var arr [5]int = [5]int{0,1,2,3,4}
	var slice1 []int = arr[:3]
	var slice2 []int = slice1[1:2]
	slice2[0] = 100
	fmt.Println(arr) //[0 100 2 3 4]
	fmt.Println(slice1) //[0 100 2]
	fmt.Println(slice2) //[100]
}

2.4 切片的遍历

package main
import "fmt"

func main(){
	//定义一个切片
	slice := []int{1,2,3,4,5}
	//方式一:for
	for i := 0; i < len(slice); i++ {
		fmt.Println(slice[i]) //1 2 3 4 5
	}
	//方式二:for-range
	for _,v := range slice{
		fmt.Println(v) //1 2 3 4 5
	}
}

 

2.5 切片的动态增长

package main
import "fmt"

func main(){
	var arr [5]int = [5]int{0,1,2,3,4}
	slice := arr[2:]
	fmt.Println(slice) //[2 3 4 0 0]
	slice = append(slice, 1,2,3,4)
	fmt.Println(slice) //[2 3 4 1 2 3 4]
	slice1 := append(slice,100,200,300)
	fmt.Println(slice1) //[2 3 4 1 2 3 4 100 200 300]
}
package main
import "fmt"
func main(){
        //定义数组:
        var intarr [6]int = [6]int{1,4,7,3,6,9}
        //定义切片:
        var slice []int = intarr[1:4] //4,7,3
        fmt.Println(len(slice))
        slice2 := append(slice,88,50)
        fmt.Println(slice2) //[4 7 3 88 50]
        fmt.Println(slice)
        //底层原理:
        //1.底层追加元素的时候对数组进行扩容,老数组扩容为新数组:
        //2.创建一个新数组,将老数组中的4,7,3复制到新数组中,在新数组中追加88,50
        //3.slice2 底层数组的指向 指向的是新数组 
        //4.往往我们在使用追加的时候其实想要做的效果给slice追加:
        slice = append(slice,88,50)
        fmt.Println(slice)
        //5.底层的新数组 不能直接维护,需要通过切片间接维护操作。
}


可以通过append函数将切片追加给切片:

 

2.6 切片的拷贝

使用函数:copy(目标切片,源切片)

package main
import "fmt"
func main(){
        //定义切片:
        var a []int = []int{1,4,7,3,6,9}
        var b []int = make([]int,10)
        //拷贝:
        copy(b,a) //将a中对应数组中元素内容复制到b中对应的数组中
        fmt.Println(b) //[1 4 7 3 6 9 0 0 0 0]
}

3、映射

映射(map), Go语言中内置的一种类型,它将键值对相关联,我们可以通过键 key来获取对应的值value。 
 

3.1 语法

语法:var 变量名 map[keytype]valuetype


注意:key、value的类型:bool、数字、string、指针、channel 、还可以是只包含前面几个类型的接口、结构体、数组,key不可以是slice、map、function


特点:

  • map集合在使用前一定要make
  • map的key-value是无序的
  • key是不可以重复的,如果遇到重复,后一个value会替换前一个value
  • value可以重复的

3.2 创建方式

package main
import "fmt"
func main(){
        //方式1:
        //定义map变量:
        var a map[int]string
        //只声明map内存是没有分配空间
        //必须通过make函数进行初始化,才会分配空间:
        a = make(map[int]string,10) //map可以存放10个键值对
        //将键值对存入map中:
        a[20095452] = "张三"
        a[20095387] = "李四"
        //输出集合
        fmt.Println(a)
        //方式2:
        b := make(map[int]string)
        b[20095452] = "张三"
        b[20095387] = "李四"
        fmt.Println(b)
        //方式3:
        c := map[int]string{
                20095452 : "张三",
                20098765 : "李四",
        }
        c[20095387] = "王五"
        fmt.Println(c)
}

3.3 map的操作

增加和更新操作:

map["key"]= value , 如果key还没有,就是增加,如果key存在就是修改。

删除操作:
delete(map,"key") , delete是一个内置函数,如果key存在,就删除该key-value,如果key不存在,不操作,但是也不会报错

清空操作:

如果我们要删除map的所有key ,没有一个专门的方法一次删除,可以遍历一下key,逐个删除

或者map = make(...),make一个新的,让原来的成为垃圾,被gc回收

查找操作:

value ,bool = map[key]

value为返回的value,bool为是否返回 ,要么true 要么false 

package main
import "fmt"
func main(){
        //定义map
        b := make(map[int]string)
        //增加:
        b[20095452] = "张三"
        b[20095387] = "李四"
        //修改:
        b[20095452] = "王五"
        //删除:
        delete(b,20095387)
        delete(b,20089546)
        fmt.Println(b)
        //查找:
        value,flag := b[200]
        fmt.Println(value)
        fmt.Println(flag)
}

 获取长度:len函数

 遍历:for-range

package main
import "fmt"
func main(){
	//定义map变量
	//make5个键值对
	var mp map[string]string = make(map[string]string,5)
	mp["string"] = "字符串"
	mp["int"] = "整型"
	mp["float"] = "浮点型"
	mp["bool"] = "布尔型"
	mp["array"] = "数组"
	//遍历map
	for k,v := range mp{
		fmt.Printf("key = %v,value = %v\n",k,v)
	}
}

相关文章