13、做中学 | 初一下期 Golang数组与切片

每当一个新事物出现的时候,我们要先接近、认识、模仿、练习、反思、到最后的实战

一、接近数组与切片

1. 看过西游记吗?

在这里插入图片描述

在生活中或者小说故事中,我们总能看到团伙、帮派,在编程里也有同样的概念,数组:同一种数据类型的多个值为数组。

就是同一伙人(数据类型),算是一个数组,不能有其它团伙(数据类型)在自己团队卧底!

比如:我们看的西游记师徒取经为一个团队(数据类型为名称),他们就可以看作一个数组:

package main

import "fmt"

func main() {
	// 西游记师徒五人
	sunWuKong := "孙悟空"
	zhuBaJie := "猪八戒"
	shaHeShang := "沙和尚"
	tangSen := "唐僧"
	baiLongMa := "白龙马"

	// 组成了一个团队==数组
	team := [5]string{sunWuKong, zhuBaJie, shaHeShang, tangSen, baiLongMa}
	fmt.Println("西游记取经团队:", team)
	// 西游记取经团队: [孙悟空 猪八戒 沙和尚 唐僧 白龙马]

}

2. 军训过吗?

在这里插入图片描述

在军训过程中,还记得怎么报数吗?从左到右,从右到左,我们报的数是什么意思,答案是位置(这个很关键,要记住)。
如果教官要让第3个人出列,之前报过3的就会上前一步;如果教官要让报过2-5的人出列,那之前报过2-5的人就会上前一步;这些口令就是切片!

口令(切片):报数2-5上前一步(切片内容)!

二、数组

了解了一组同类型的数据封装为数组,那如何声明,如何使用呢?

1. 声明数组

声明数组的格式如下

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

	// 第一种声明
	var arr1 [3]int = [3]int{1, 2, 3}
	// 第二种声明 后边有具体值,可以进行推导,前边定义的数组大小和类型可以省略
	var arr2 = [3]int{1, 2, 3}
	// 第三种声明 直接赋值可以知道数组大小,可以省略前边的定义数组大小
	var arr3 = [...]int{1, 2, 3}
	// 第四种申明 通过索引,进行赋值
	var arr4 = [...]int{0: 1, 1: 2, 2: 3}
	fmt.Println(arr1, arr2, arr3, arr4)
	// [1 2 3] [1 2 3] [1 2 3] [1 2 3]

2. 使用数组

定义了数组,接下来就是使用了,还记得之前要让记住的内容吗(位置很重要,要记住)!
数组就是通过位置去进行修改和调用

	var arr [3]int
	arr[0] = 10
	arr[1] = 20
	fmt.Println(arr[0], arr[1])
	// 10 20

go数组,使用下标的方式进行赋值

就像标兵1号给与冲锋枪一把,标兵2号给与手榴弹三颗
只有叫对了人,才能给与相应的值

3. 数组内存分布

把上边例子进行内存地址打印如下

	var arr [3]int
	arr[0] = 10
	arr[1] = 20
	fmt.Println(arr[0], arr[1], arr[2])
	// 10 20 0
	fmt.Printf("arr的内存地址=%p, arr[0]的内存地址=%p, arr[1]的内存地址=%p, arr[2]的内存地址=%p", &arr, &arr[0], &arr[1], &arr[2])
	// arr的内存地址=0xc0000160c0, arr[0]的内存地址=0xc0000160c0, arr[1]的内存地址=0xc0000160c8, arr[2]的内存地址=0xc0000160d0

上边的代码,内存地址如下
在这里插入图片描述

  1. 第三位我没有赋值,也就是数组已经进行了开辟空间,并进行赋值为0。
  2. 确定了数据类型为int后,进行开辟空间,16位内存地址间隔为8字节(64位操作系统)。
  3. 从图中可以看到arr的地址和下标为0的地址一样,数组的地址为第一位的地址。

4. 数组的使用

遍历数组,在go中有一种独有的结构,进行遍历数组,即for–range

	for index, value := range arr {
		fmt.Printf("下标index=%d, 遍历值value =%d\n", index, value)
	}
	//下标index=1, 遍历值value=20
	//下标index=2, 遍历值value=0
  1. 在遍历过程中,index为下标,value为值
  2. index和value是我自己定义的,当然你可以定义其它名称,但对应的位置含义不变
  3. 遍历过程中,index,value只在循环体内可见的局部变量

三、切片

上边内容有说,军训时排成一列,让报2-5的上前一步!那这2-5的出来的同学组成了什么呢?呼之欲出的:切片!

1. 啥是切片

炒菜时,切的一片片的菜,这种就叫切片!
切片不是新的东西,而是从之前的东西选择了一部分,被叫做切片!

切片:是引用类型,引用了相应的类型数据,一部分内容

2. 声明切片

切片声明有俩种,一种是直接拿别人的蔬菜进行切片,一种是自己种蔬菜并切片

  1. 拿别人的蔬菜进行切片
	// 创建数组
	var arr [5]int = [5]int{1, 2, 3, 4, 5}

	// 创建切片 切出数组中索引为1到3的元素
	var slice []int = arr[1:3]
	fmt.Println(slice)
	// [2 3]

根据创建好的数组,直接根据索引进行切片

  1. 自己种蔬菜并切片
	// 使用make进行创建切片
	var slice2 []int = make([]int, 5, 10)
	slice2[0] = 10
	slice2[1] = 20
	slice2[2] = 30
	fmt.Println(slice2)
	// [10 20 30 0 0]

使用make创建切片结构:var 切片名称 []Type = make([]Type, len, cap)
其中,make参数示意如下:

  1. []int:数据类型
  2. len: 切片长度
  3. cap:切片容量 cap>= len

3. 切片内存

3.1 拿别人的菜进行切片

	// 创建数组
	var arr [5]int = [5]int{1, 2, 3, 4, 5}

	// 创建切片 切出数组中索引为1到3的元素
	var slice []int = arr[1:3]
	fmt.Printf("arr = %p, slice = %p \n", &arr[1], slice)
	// arr = 0xc00000e458, slice = 0xc00000e458

在这里插入图片描述
截取下标1到3的片段(顾头不顾尾法截取),下标为1的地址为:0xc00000e458,而切片就以第一个值的地址为切片地址。

3.2 自己种菜进行切片

	// 使用make进行创建切片
	var slice2 []int = make([]int, 5, 10)
	slice2[0] = 10
	slice2[1] = 20
	slice2[2] = 30
	fmt.Printf("slice2 = %p \n", slice2)
	// 0xc0000142d0

在这里插入图片描述
使用make,进行创建int类型,长度为5,容量为10的数组,并进行地址引用给切片

数组与切片:数组可以理解为母体,切片可以理解为子体

4. 切片的遍历

切片是数组的一部分,用法和数组基本一样,比如数组的遍历和切片的遍历:

// 使用make进行创建切片
	var slice2 []int = make([]int, 5, 10)
	slice2[0] = 10
	slice2[1] = 20
	slice2[2] = 30

	for index, value := range slice2 {
		fmt.Println(index, value)
	}
	//0 10
	//1 20
	//2 30
	//3 0
	//4 0

本篇进行学习数组过程中,由于数组长度是不支持动态扩容,但有这种需求,进而产生了切片的概念!
切片是数组的一部分,而且青出于蓝而胜于蓝,切片是支持动态扩容!

重要说明:

  • Go语言中只有数组、字符串和切片本身支持切片操作(使用[start:end]语法)
  • 其他数据类型如map、chan、struct等不支持切片操作 切片操作的语法只能用于具有索引访问能力的数据类型
  • 字符串切片会产生一个新的字符串,而数组切片会产生一个指向原数组的切片

因此,严格来说,Go语言中只有数组和字符串这两种基本数据类型可以直接进行切片操作,切片本身也可以再次切片。

<think>首先,用户的问题是:“golang 数组切片”,翻译成英文是“Golang array take slice”。我需要用中文回答这个问题。问题似乎是关于如何在Go语言中从数组获取切片。 关键点是: - 使用中文回答问题。 - 回答后,必须提出3-5个相关问题。 - 相关问题必须以“§§相关问题§§”开头,且在第一行完整输出。 - 禁止换行分散,意思是相关问题的列表应该紧凑,没有额外的换行。 - 最后,所有内容必须符合规则,否则回答无效。 回顾示例格式: - 首先,回答问题的内容。 - 然后,输出“§§相关问题§§”,紧接着是相关问题列表,如“1. ··· 2. ··· 3. ···”,没有换行分散。 所以,我的回答结构应该是: 1. 解释如何在Go中从数组获取切片。 2. 以中文回答。 3. 结束时,输出“§§相关问题§§”,然后列出3-5个相关问题。 现在,内容部分: - 在Go中,数组是固定大小的,切片是动态大小的视图。 - 要从数组获取切片,可以使用切片操作符:`array[start:end]`,其中start和end是索引。 - 例如:`arr := [5]int{1,2,3,4,5}`,然后 `slice := arr[1:4]` 会得到 `[2,3,4]`。 - 解释基本概念。 确保回答简洁明了。 然后,提出相关问题: - 相关问题应该基于用户的问题和我的回答。 - 用户的问题是“golang 数组切片”,所以相关问题可能涉及: 1. 切片数组的区别。 2. 如何修改切片影响原数组。 3. 切片的基本操作。 4. 性能考虑。 5. 常见错误。 列出3-5个: 1. Go语言数组切片的主要区别是什么? 2. 如何从切片创建新的切片? 3. 修改切片会影响原始数组吗?为什么? 4. 在Go中,切片的容量和长度如何工作? 5. 如何避免在切片操作中出现索引越界错误? 确保问题是相关的。 最后,输出格式: - 回答内容。 - 然后,直接“§§相关问题§§”后跟问题列表,例如: §§相关问题§§ 1. ... 2. ... 3. ... 没有额外的换行。 编写回答: - 先用中文解释。 - 可能包括一个简单的代码示例,因为用户提到了“golang”,类似于示例中的Python代码。 - 示例格式有代码块,所以我应该包括一个Go代码示例。 用户问题:“golang 数组切片”,所以重点是操作。 代码示例: ```go package main import "fmt" func main() { // 定义一个数组 arr := [5]int{1, 2, 3, 4, 5} // 从数组切片 slice := arr[1:4] // 索引从1开始到4(不包括4),所以是元素2,3,4 fmt.Println(slice) // 输出: [2 3 4] } ``` 在回答中包括这个。 然后结束。</think>在 Go 语言中,数组是固定大小的序列,而切片是动态大小的视图,可以基于数组创建。要从数组获取切片,使用切片操作符 `[start:end]`,其中 `start` 是起始索引(包含),`end` 是结束索引(不包含)。索引从 0 开始,如果省略 `start` 则默认为 0,省略 `end` 则默认为数组长度。切片是引用类型,修改切片会影响原数组。 示例代码: ```go package main import "fmt" func main() { // 定义一个数组 arr := [5]int{10, 20, 30, 40, 50} // 从数组切片:索引1到3(不包含3) slice := arr[1:3] fmt.Println(slice) // 输出: [20 30] // 修改切片会影响原数组 slice[0] = 99 fmt.Println(arr) // 输出: [10 99 30 40 50] } ``` 在这个例子中,`arr[1:3]` 创建了一个包含原数组索引 1 和 2 元素的切片切片共享底层数组数据,因此对切片的修改会反映到原数组上。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值