首页 > 其他分享 >Go语言数组与切片学习总结

Go语言数组与切片学习总结

时间:2023-10-28 18:12:08浏览次数:40  
标签:int s1 切片 Println 数组 Go fmt

一.数组

  • 数组的定义:相同类型的数据集合
  • go语言中数组的索引从0开始
  • 没有赋值的数值型数组,默认值为0
  • 数组一旦被创建,它的大小就是不可改变的

(1)声明数组与打印

var 变量名 [大小]变量类型

 //数组的声明
var nums [4]int       

//数组的赋值
nums[0] = 1
nums[1] = 2
nums[2] = 3
nums[3] = 4

/***************数组的打印*************/
fmt.Printf("%T\n", nums)     //打印数组的类型:[4]int
fmt.Println(nums[3])         //打印单个数组的值:4
fmt.Println("长度:", len(nums))    //打印数组的长度:4
fmt.Println("容量:", cap(nums))    //打印数组的容量:4

(2)数组的初始化

在go语言中,数组有多种初始化方式。

  • 常量初始化定义数组
  • 快速的定义数组
  • 定义不确定长度的数组
  • 给指定下标进行赋值操作
	//1、常量的初始化定义数组
	var arrs1 = [5]int{1, 2, 3, 4, 5}

	//2、快速定义数组
	arrs2 := [5]int{6, 7, 8, 9, 10}

	//3、定义不确定长度的数组
	arrs3 := [...]string{"hello", "xuexiangban", "kuangshenshuo"}

	//4、给指定下标进行赋值操作
	arrs4 := [5]int{1: 100, 3: 200}//给下标为1赋值为100,下标为3赋值为200

(3)数组的遍历

  • for循环遍历
	//1、for循环遍历数组
	arr1 := [5]int{1, 2, 3, 4, 5}    //创建数组
	for i := 0; i < len(arr1); i++ {
		fmt.Println(arr1[i])
	}
/*输出结果:
1
2
3
4
5
*/
  • for-range遍历方式
	//2、forage循环遍历数组
	for index, value := range arr1 { //index下标,value对应的值
		fmt.Println(index, value)
	}
/*输出结果:
0 1
1 2
2 3
3 4
4 5
*/

(4)数组是值传递类型

  • 在go语言中,数组被看作是值传递类型,因此数组之间可以直接相互赋值
	arr1 := [3]int{1, 2, 3}         //创建数组1:整型
	arr2 := [2]string{"hello", "xuexiangban"}   //创建数组2:字符型
	arr3 := arr1                //创建数组3直接被赋值数组1
	fmt.Println(arr1, arr3)   //打印结果:[1 2 3] [1 2 3]
	arr3 = [3]int{4, 5, 6}    //重新赋值
	fmt.Println(arr1, arr3) //[1 2 3] [4 5 6]

(5)多维数组

  • go语言支持多维数组,以下为常用的多维数组声明方式
var 变量名[SIZE1][SIZE2]...[SIZEN]变量类型
  • 多维数组定义示例:
	arr := [3][4]int{
		{1, 2, 3, 4},
		{5, 6, 7, 8},
		{9, 10, 11, 12},
	}
  • 多维数组使用示例
	//forage循环输出
	for _, i := range arr {
		fmt.Println(i)        //打印外层
		fmt.Println("=========")   //打印内层
		for _, i2 := range i {
			fmt.Println(i2)
		}
	}

/*打印结果:
[1 2 3 4]
=========
1
2
3
4
[5 6 7 8]
=========
5
6
7
8
[9 10 11 12]
=========
9
10
11
12

*/

二.切片

Go语言切片是对数组的抽象

go语言数组的长度是不可改变的切片的长度是不固定的可以追加元素,在追加时可能使切片的容量增大

切片是一种方便、灵活且强大的包装器,切片本身没有任何数据,他们只是对现有数组的引用

切片与数组相比,不需要设定长度,在[]中不用设定值,相对来说比较自由

(1)定义创建切片

切片与数组在定义时不同,可以不用指定长度容量

	//1、定义一个切片,里面不添加数据,打印输出
	s1 := []int{}
	fmt.Println(s1) //输出结果:[]

	//2、定义切片向里面添加数据,打印输出类型
	s2 := []int{1, 2, 3}
	fmt.Println(s2)         //输出结果:[1 2 3]
	fmt.Printf("%T", s2)   //输出结果[]int

补充:长度(length)和容量(cap)区别

  • 长度(length)指切片中当前包含的元素个数。使用内置函数len()可以获取切片的长度。

  • 容量(capacity)指分配给切片的底层数组中可用于存储元素的空间大小。容量至少等于切片长度,但可能会更大以容纳未来的增长。使用内置函数cap()可以获取切片的容量。

  • 在创建切片的时候,可以只指定长度也可以同时指定长度和容量。当只指定长度时,切片的容量与长度相等。当同时指定长度和容量时,切片的容量可以大于长度。

(2)make函数创建切片

make函数创建切片,可以指定切片的长度和容量

make([]T,length,capactity)   //类型,长度,容量
  • 使用示例
	//1、通过make函数来创建切片
	s1 := make([]int, 5, 10) //长度:5,容量为10
	//2、给切片里面的元素进行赋值
	s1[0] = 100
	//3、打印输出长度,容量
	fmt.Println(s1)
	fmt.Println("长度:", len(s1))
	fmt.Println("容量:", cap(s1))

(3)切片扩容append

  • 注意:追加数据超过容量后,容量只会2倍扩容地址会发生改变
	//1、创建一个切片s1
	s1 := make([]int, 2, 4)
	fmt.Println("追加数据前的长度和容量:", len(s1), cap(s1))
	//2、s1通过append追加数据
	s1 = append(s1, 1, 2, 3, 4) //追加数据,不是添加数据
	fmt.Println(s1)
	fmt.Println("追加数据后的长度和容量:", len(s1), cap(s1))

	//	3、创建一个s2,将s2中数据追加到s1
	s2 := make([]int, 3, 3)
	s2 = []int{1, 2, 3}
	s1 = append(s1, s2...) //将s2里面的数据追加到s1
	fmt.Println(s1)

(4)在已有数组上创建切片

从已有的数组上,直接创建切片,该切片的底层数组就是当前的数组,长度是从start到end切到的数据量,但是容量从start到数组的末尾。

从数组上创建的切片,地址与数组是一样的,因此修改数组或切片的某个值,对应的数组/切片的值也会改变

slice := arr[start:end]

	//定义数组和其切片
	arr := [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

	s1 := arr[:5]  //切片从1-5 [1 2 3 4 5]
	s2 := arr[4:8] //[5 6 7 8]
	s3 := arr[5:]  //[6 7 8 9 10]
	s4 := arr[:]   //[1 2 3 4 5 6 7 8 9 10]
	fmt.Println(s1)   //[1 2 3 4 5]
	fmt.Println(s2)   //[5 6 7 8]
	fmt.Println(s3)   //[6 7 8 9 10]
	fmt.Println(s4)   //[1 2 3 4 5 6 7 8 9 10]

	//修改数组的某个值
	arr[0] = 100 //将数组元素值进行更换
	fmt.Println(arr)      //[100 2 3 4 5 6 7 8 9 10]
	fmt.Println(s1)	       //[100 2 3 4 5 6 7 8 9 10]

	//修改切片的某个值
	s1[1] = 100 
	fmt.Println(arr)    //[100 100 3 4 5 6 7 8 9 10]
	fmt.Println(s1)	    //[100 100 3 4 5]

    //查看数组和对应切片的地址
	fmt.Printf("%p\n", s1)   //0xc0000ac0f0
	fmt.Printf("%p\n", &arr)  //0xc0000ac0f0

(5)切片是引用类型

  • 与数组不同,数组是值传递类型,而切片是引用类型
  • 数组之间可以直接赋值,改变其中一个数组的值,另一个数组的值不会发生改变
  • 切片之间若直接赋值,则改变其中一个切片的值,另一个切片的值同样发生改变
	s1 := []int{1, 2, 3, 4, 5}
	s2 := s1
	s2[0] = 100
	fmt.Println(s1, s2)          //切片2里元素发生变化,切片1也会跟随着变化
	fmt.Printf("%p\t%p", s1, s2) //说明切片的copy指向的是地址

(6)copy深拷贝与浅拷贝

  • 深拷贝:拷贝的是数据本身
  • 浅拷贝:拷贝的是数据的地址,会导致多个变量指向同一块内存
  • 引用类型的数据,默认都是浅拷贝,如切片,集合
  • 可以用copy强制实现深拷贝

实现切片的深拷贝

	//1、通过for循环实现切片的深拷贝
	s1 := []int{1, 2, 3, 4}
	s2 := make([]int, 0, 0)
	for i := 0; i < len(s1); i++ {
		s2 = append(s2, s1[i])
	}
	fmt.Println(s1, s2)
	//2、通过copy操作实现深拷贝
	s3 := []int{5, 6, 7, 8}
	fmt.Println(s1, s3)
	copy(s3, s1) //(接收者,传递者) 将s1 copy 给s3
	fmt.Println(s1, s3)

标签:int,s1,切片,Println,数组,Go,fmt
From: https://www.cnblogs.com/sillyfox/p/17794397.html

相关文章

  • 用go封装一下临时token
    用go封装一下临时token本篇为用go设计开发一个自己的轻量级登录库/框架吧的临时token篇,会讲讲临时token的实现,给库/框架增加新的功能。Github:https://github.com/weloe/token-go临时token也算是比较常见的业务,例如登录验证码信息,邀请链接等等,都属于临时token的范畴。在token-......
  • 【pwn】[MoeCTF 2022]babyfmt --格式化字符串漏洞,got表劫持
    拿到程序,先checksec一下发现是PartialRELRO,got表可修改当RELRO保护为NORELRO的时候,init.array、fini.array、got.plt均可读可写;为PARTIALRELRO的时候,ini.array、fini.array可读不可写,got.plt可读可写;为FULLRELRO时,init.array、fini.array、got.plt均可读不可写。然后看主......
  • 创建一个django项目
    1.创建一个django项目在pycharm里面创建一个django的新项目在项目配置的时候选择好第一个app,templates文件和python环境(在环境里要先下好django)我这里用的是conda管理的环境django里面的目录结构最外层的是本项目名字的一个app,一个users的app,templates模板文件,manages.py(......
  • 深入研究:Go语言文件写入的性能差异 原创 Go先锋 Go先锋
    深入研究:Go语言文件写入的性能差异原创 Go先锋 Go先锋 2023-10-2811:03 发表于广东收录于合集#Go语言包22个#性能效率1个Go先锋读完需要7分钟速读仅需3分钟  概述在Go语言开发中,文件操作是一个非常常见的任务。在不同的应用场景下,可能会面临选......
  • 使用数组实现一个小顶堆
    堆也叫优先队列,可以在\(\mathcal{O(1)}\)时间里得到堆中的最小/大元素。堆在各种编程语言中都有实现,c++STL里面有priority_queue,java中是Priority_Queue,python里提供了heapp模块实现对堆的各种操作。堆可以分为小顶堆和大顶堆,顾名思义,小顶堆堆顶存储堆中的最小值,大顶堆堆顶存储堆......
  • PAT_B1008 数组元素循环右移问题
    一个数组A中存有N(>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向右移M(≥0)个位置,即将A中的数据由(A0​A1​⋯AN−1​)变换为(AN−M​⋯AN−1​A0​A1​⋯AN−M−1​)(最后M个数循环移至最前面的M个位置)。如果需要考虑程序移动数据的次数尽量少,要如何设计移动的方法?输入格式:每......
  • C#读取记事本,里面有600万条数据,放入数组时:System.OutOfMemoryException
     原因:使用文件流,然后读取文件内容,再解析的时候,会报内存溢出 处理办法:使用/n分隔///<summary>///通过记事本,获取CRM所有客户的某个字段///</summary>///<returns></returns>publicstaticList<string>GetFieldByText(str......
  • Python 框架学习 Django篇 (六) 数据表关联、ORM关联
    在后端服务器开发中,特别是前后端分离的架构中数据库是非常重要的,后端主要就是负责管理数据,而我们经常使用的mysql、oracle都是关系型数据库,什么是关系型数据库?就是建立在关系模型基础上的数据库,而最难处理的就是各个表之间的关联关系,一般这种关系分为三种:一对一、一对多、多对......
  • Python 框架学习 Django篇 (六) ORM关联
    像是上一章我们很少会通过页面点击去添加和绑定关系表,更多的时候都是通过django的语法实现,接下来我们做一个案例djangorom是怎么操作外键关系的创建mode模型表Django_demo/mgr/models.py#国家表classCountry(models.Model):name=models.CharField(max_length=100)#......
  • [TopCoder 13001] BigO 题解
    [TopCoder13001]BigO题解题目描述给定一张有向图,当\(L\)趋近于无穷大时,长度为\(L\)的路径条数有\(S\)条,此时若\(S=O(L^k)\),输出\(k\),否则如果没有多项式的大O表示法,输出\(-1\)。指数情况首先如果一张图中存在如下强连通分量,则\(S=O(2^L)\)。因为每次到1......