Go基础——数组、切片、集合

目录

  • 1、数组
  • 2、切片
  • 3、集合
  • 4、范围(range)

1、数组

数组是具有相同唯一类型的一组已编号且长度固定的数据项序列,这种类型可以是任意的原始类型例如整型、字符串或者自定义类型。
Go 语言数组声明需要指定元素类型及元素个数,与C语言稍微有所区别:

package mainimport "fmt"func main() {var array1 [10]intarray1 = [10]int{1, 2, 3}              // 未赋值的数组位补0var array2 = [5]string{"a", "b"}       // 未赋值的数组位补空值array3 := [...]float32{1: 1.1, 2: 2.3} // 定义未确定长度的数组,并且给索引1和索引2赋值fmt.Println(array1)fmt.Println(array2)fmt.Println(array3)// 如果忽略 [] 中的数字不设置数组大小,Go 语言会根据元素的个数来设置数组的大小array4 := []int{1, 2, 3}  // 实际为切片fmt.Println(array4)array5 := add(array4) // 将数组作为参数传递fmt.Println(array5)
}func add(arr []int) []int { sum := 0for i := 0; i < len(arr); i++ { // 与python一样,len计算长度sum += arr[i]arr[i] += 1}fmt.Println("re:", sum)return arr
}

注意:在 Go 语言中,数组的大小是类型的一部分,因此不同大小的数组是不兼容的, [5]int 和 [10]int 是不同的类型。形参数组定义长度须与传参保持一致,函数传参时需特别注意!
多维数组与其他语言类似:

package mainimport "fmt"func main() {arrays := [5][5]int{{1, 2, 3, 4, 5},{9, 8, 7, 6, -1},}fmt.Println(arrays)access(arrays)
}
func access(arr [5][5]int) {  // 形参数组定义长度须与传参保持一致// 可通过len得到数组长度,用于不知道数组长度时rows := len(arr)    // 数组行数cols := len(arr[0]) // 数组列数for i := 0; i < rows; i++ {for j := 0; j < cols; j++ {fmt.Print(arr[i][j])}fmt.Print("\n")}
}

数组对比:可判断两个数组的元素是否相同,但两数组长度不相等是不能进行 == 运算

 func contrast() {array1 := [4]int{1, 2, 3, 4}array2 := [4]int{1, 1, 2, 3}fmt.Println(array1 == array2)   // false
}

在这里插入图片描述

2、切片

Go 语言切片是对数组的抽象。Go 数组的长度不可改变,在特定场景中这样的集合就不太适用,Go 中提供了一种灵活,功能强悍的内置类型切片(“动态数组”),与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大。

// 声明一个未指定大小的数组来定义切片:
var identifier []type

上代码:

package mainimport ("fmt""reflect"
)func main() {array := [5]int{1, 2, 4, 5, 6}fmt.Println("array 类型:", reflect.TypeOf(array)) // array 类型: [5]ints := array[:]fmt.Println("s 类型:", reflect.TypeOf(s)) // s 类型: []intfmt.Println(s)                          // [1 2 4 5 6]// 切片,跟其他语言一样,左闭右开sli1 := array[1:3]sli2 := array[:len(array)-1]sli3 := array[0:]// sli1 := array[1:]// sli1 := array[1:]slic4 := make([]int, 2, 3)  // 长度为2,容量为3的切片fmt.Println(sli1) // [2 4]fmt.Println(sli2) // [1 2 4 5]fmt.Println(sli3) // [1 2 4 5 6]fmt.Println(sli4)  // [0 0]  make创建的切片初始值为0,不等于nilslis()
}func slis() {array1 := [8]int{1, 2, 3, 4}s1 := array1[:]s2 := []int{1, 2, 5, 7}var s3 []int                         // 允许创建nil 空切片fmt.Println("array1-cap: ", cap(s1)) // array1-cap:  8fmt.Println("s2-cap: ", cap(s2))     // s2-cap:  4if s3 == nil {                       // nil是一种特殊的值,表示没有任何指针指向的对象。相当于nullfmt.Println("s3-cap: ", cap(s3)) // 0}array2 := []int{8, 9, 3, 4, 5, 6, 7, 8, 9}fmt.Println("array2-cap: ", array2, cap(array2))array2 = append(array2, 1)fmt.Println("array2-append-cap: ", array2, cap(array2))}

切片可以看做是一个数组,索引、访问都是一样的,并且可以进行增删。
切片除了长度(len),还有容量(cap):容量(capacity)表示切片底层数组中可以容纳的元素数量。切片的容量可以预先分配更多的内存空间,以减少在运行时动态扩展切片的开销。当知道切片可能需要的最大元素数量时,可以通过设置合适的容量来避免频繁的内存分配和数据复制。切片的容量可以用于控制内存的使用。当创建一个切片时,Go语言会根据切片的长度和容量分配相应的内存空间。通过合理设置切片的容量,可以更好地控制内存的使用情况,避免不必要的内存浪费。但是切片的容量并不限制切片的长度,切片的长度可以根据需要动态增长,只要不超过容量的上限。当切片的长度超过容量时,Go语言会自动分配更大的内存空间(一般自动分配为原容量的2倍),并将原有数据复制到新的内存位置。因此,合理地设置切片的容量可以提高程序的性能和内存管理效率,但需要根据具体的应用场景和数据规模来进行权衡和选择。

append()函数:向slice里面追加一个或多个元素,然后返回一个和slice一样类型的slice。通过append也可实现对切片元素的删除。

arr := []int{1, 2}
arr = append(arr, 3, 4, 5, 6, 7, 8, 'a')  // 单引号返回字符ASCII值
fmt.Println(arr)  // [1 2 3 4 5 6 7 8 97]arrs := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
arrs = append(arrs[:1], arrs[4:]...)  // 删除索引1到索引3处的元素
fmt.Println(arrs)   // [1 5 6 7 8 9]

copy()函数:用于将源切片中的元素复制到目标切片中。

func copy(dst_slice, src_slice []Type) int

dst_slice是目标切片,src_slice是源切片,Type是切片元素的类型。函数返回为一个整数值,表示实际复制的元素个数(即src和dst的最小长度)

  • dst_slice和src_slice的底层数组必须是相同类型的。例如,不能将一个 []int 类型的切片复制到一个 []string 类型的切片中。
  • copy() 函数不会对切片本身进行初始化,所以在使用 copy() 之前,必须确保目标切片 dst_slice 已经初始化。
  • copy() 不会自动扩容:copy() 函数只会复制dst_slice 切片能容纳的元素数量,如果dst_slice 的容量不足以容纳 src_slice 的所有元素,多余的元素将被丢弃。如果需要将src_slice切片的所有元素复制到dst_slice切片中,并且确保 dst_slice具有足够的容量,需要在复制前先对 dst进行扩容。可以使用 append() 函数来实现切片的扩容,然后再调用 copy() 函数进行复制。
  • copy()函数会将src_slice中的元素逐个复制到dst_slice,不会对切片进行扩容或缩容。
  • copy()函数不会创建新的切片,它只是修改目标切片的内容。
func sli_copy() {sli1 := []int{9, 8, 7, 6, 5, 4}sli2 := make([]int, 6)num := copy(sli2, sli1)fmt.Println(sli2, num) // [9 8 7 6 5 4]  6sli3 := make([]int, 2)  num2 := copy(sli3, sli1)  // copy 到短切片fmt.Println(sli3, num2) // [9 8] 2sli4 := make([]int, len(sli3))_ = copy(sli4, sli3)  // 切片copy后,内存地址不同fmt.Printf("Address: slic3:%p  slic4: %p", sli3, sli4)  // Address: slic3:0xc000016190  slic4: 0xc0000161c0}

注意:当目标切片长度为0时,copy不会生效。如将一个长度为0的切片[]int分配给sli5。sli5的内部数组没有足够的空间来容纳copy操作中src切片中的元素。因此,copy操作不会生效,因为它没有足够的空间去存储复制的数据。

sli5 := make([]int, 0)
_ = copy(sli5, sli3)

3、集合

Go语言中Map 是一种无序的键值对的集合。Map 最重要的一点是通过 key 来快速检索数据,key 类似于索引,指向数据的值。
Map 是一种集合,所以可以像迭代数组和切片那样迭代它。不过,Map 是无序的,遍历 Map 时返回的键值对的顺序是不确定的
在获取 Map 的值时,如果键不存在,返回该类型的零值,例如 int 类型的零值是 0,string 类型的零值是 “”。Map 是引用类型,如果将一个 Map 传递给一个函数或赋值给另一个变量,它们都指向同一个底层数据结构,因此对 Map 的修改会影响到所有引用它的变量。

/* 使用 make 函数 */
map_variable := make(map[KeyType]ValueType, initialCapacity)

其中 KeyType 是键的类型,ValueType 是值的类型,initialCapacity 是可选的参数,用于指定 Map 的初始容量。Map 的容量是指 Map 中可以保存的键值对的数量,当 Map 中的键值对数量达到容量时,Map 会自动扩容。如果不指定 initialCapacity,Go 语言会根据实际情况选择一个合适的值。

func MapCreate() {map1 := make(map[string]int) // 空mapmap1["a"] = 1                // 与python一样,直接访问键,增加或修改值fmt.Println(len(map1))       // 1map2 := map[string]float32{ // 字面量创建"aa": 1.5,"bb": 2.0,"cc": 3.36,}fmt.Println(map2)// 遍历for k, v := range map2 {fmt.Printf("key=%s, value=%.2f\n", k, v)}// 删除delete(map2, "cc")fmt.Println(map2) // map[aa:1.5 bb:2]
}

delete() 函数用于删除集合的元素, 参数为 map 和其对应的 key。如果map中不存在指定的键,那么delete函数什么也不做。

4、范围(range)

range 关键字用于 for 循环中迭代数组(array)、切片(slice)、通道(channel)或集合(map)的元素。在数组和切片中它返回元素的索引和索引对应的值,在集合中返回 key-value 对。
先看切片的range:

	for i, v := range pow {fmt.Printf("索引:%d, 元素:%d \n", i, v)}// 此时遍历得到的是索引for i := range pow {fmt.Printf("%d ", i)}fmt.Printf("\n")// 此时遍历得到的是索引for _, v := range pow {fmt.Printf("%d ", v)}fmt.Printf("\n")// 不需要使用内部元素时lens := 0for range pow {lens++}

集合的range:

func MapRange() {map1 := map[string]int{"num1": 100,"num2": 101,"num3": 102,"num4": 103,}// 键值对遍历for key, vale := range map1 {fmt.Printf("key: %s  value: %d \n", key, vale)}// 只遍历建for key := range map1 {fmt.Printf("key: %s \n", key)}// 只遍历值for _, vale := range map1 {fmt.Printf("value: %d \n", vale)}//range也可以用来枚举 Unicode 字符串。第一个参数是字符的索引,第二个是字符(Unicode的值)本身。for i, c := range "go" {fmt.Println(i, c)}// 0 103// 1 111for i, c := range "中文啊" {fmt.Println(i, c)}// 0 20013// 3 25991// 6 21834
}

与切片类似,但比较有意思的是当range范围是字符串时,遍历返回的是字符的Unicode编码值;而且当字符串是中文时,并且采用UTF-8编码时,一个中文占用3字节,如“中文啊”字节序列为:“E4 B8 AD E6 96 87 E5 95 8A”,每个字节对应一个Unicode码点,每三个字节表示一个汉字。上述 i 则是Unicode码点的索引,c则是对应的UTF-8编码。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/121919.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Mybatis的Mapper文件报错:Tag name expected

目录 一、Mapper文件的错误信息 二、原因分析 三、解决方案 1、解决方式一&#xff1a;CDATA 2、解决方式二&#xff1a;预定义字符 一、Mapper文件的错误信息 在使用MyBatis时&#xff0c;我们通常会写一些sql语句。如下图&#xff0c;有时候我们会直接使用比较符号&…

docker 中给命令起别名

docker 的有些命令特别复杂&#xff0c;我们可以给它设置别名简化输入&#xff0c;就不用每次都输入那么多了&#xff01;&#xff01;&#xff01; 1. 进入 .bashrc 中修改配置&#xff08; .bashrc 是root下的隐藏文件&#xff09; cd /rootvim .bashrc2. 在 .bashrc 中加入…

LabVIEW开发TDS1000 和TDS2000 系列泰克示波器

LabVIEW开发TDS1000 和TDS2000 系列泰克示波器 泰克示波器是经常用到的工具&#xff0c;一般手动操作即可&#xff0c;但有时候也要集成到系统中&#xff0c;需要程控。这时候先要下载厂家提供的例子&#xff0c;了解LabVIEW的demo。根据不用的示波器型号&#xff0c;选择和计…

【Proteus仿真】【Arduino单片机】直流电机和步进电机

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真Arduino单片机控制器&#xff0c;使用蜂鸣器、按键、直流电机、步进电机、ULN2003、L293D等。 主要功能&#xff1a; 系统运行后&#xff0c;K3键启动运行&#xff0c;K1和K2键控制…

MAC安装stable diffusion

./webui.sh --precision full --no-half-vae --disable-nan-check --api Command: "/Users/xxxx/aigc/stable-diffusion-webui/venv/bin/python3" -m pip install torch2.0.1 torchvision0.15.2 Error code: 2 执行命令&#xff1a; pip install torch2.0.1 torchvi…

【LeetCode力扣】189 53 轮转数组 | 最大子数组和

目录 1、189. 轮转数组 1.1、题目介绍 1.2、解题思路 2、53. 最大子数组和 2.1、题目介绍 2.2、解题思路 1、189. 轮转数组 1.1、题目介绍 原题链接&#xff1a;189. 轮转数组 - 力扣&#xff08;LeetCode&#xff09; ​ 示例 1: 输入: nums [1,2,3,4,5,6,7], k 3输…

java原子类-Atomic

什么是原子类&#xff1f; java 1.5引进原子类&#xff0c;具体在java.util.concurrent.atomic包下&#xff0c;atomic包里面一共提供了13个类&#xff0c;分为4种类型&#xff0c;分别是&#xff1a; 原子更新基本类型&#xff0c;原子更新数组&#xff0c;原子更新引用&…

一次js请求一般情况下有哪些地方会有缓存处理

目录 前言 1. 浏览器缓存 1.1 强缓存 用法 代码 理解 1.2 协商缓存 用法 代码 理解 2. 服务端缓存 2.1 反向代理缓存 用法 代码 理解 2.2 应用层缓存 用法 代码 理解 3. CDN缓存 3.1 用法 3.2 理解 4. DNS缓存 4.1 用法 4.2 理解 5. AJAX请求缓存 5.…

【网络安全 --- 任意文件下载漏洞(1)】任意文件下载漏洞

一&#xff0c;环境&#xff0c;工具准备 1-1 VMVare 16 虚拟机及下载安装&#xff08;资源&#xff09; 请参考以下博客安装&#xff08;特详细&#xff09;&#xff1a;【网络安全 --- 工具安装】VMware 16.0 详细安装过程&#xff08;提供资源&#xff09;-CSDN博客【网络安…

Linux ln命令:建立链接文件

如果要想说清楚 ln 命令&#xff0c;则必须先解释下 ext 文件系统&#xff08;Linux 文件系统&#xff09;是如何工作的。我们在前面讲解了分区的格式化就是写入文件系统&#xff0c;而我们的 Linux 目前使用的是 ext4 文件系统。如果用一张示意图来描述 ext4 文件系统。 ext4 …

无需编程,小白也能建立个人网站

想要搭建一个属于自己的网站&#xff0c;但又不懂编程&#xff1f;别担心&#xff0c;现在有一个简单的方法可以帮助你轻松实现这个愿望。只需要几个简单的步骤&#xff0c;就可以让小白也能搭建出一个漂亮的网站。 首先&#xff0c;登录乔拓云账号&#xff0c;点击网站搭建进入…

2-多媒体数据压缩国际标准

文章目录 多媒体数据压缩编码的重要性和分类为什么要压缩?计算: 未压缩音频的数据率简答: 环绕声系统-作业题9(简述7.4.3全景声)计算: 未压缩图像的数据量-作业题10(估计尺寸及容量)计算: 未压缩视频的数据率 为什么能压缩?数据压缩编码的两大类无损压缩算法: LZ77-作业题6-(…

大数据Doris(十三):创建用户和创建数据库并赋予权限

文章目录 创建用户和创建数据库并赋予权限 一、创建用户

css-渐变色矩形

效果图&#xff1a; 代码&#xff1a; html: <!DOCTYPE html> <html><head><meta charset"utf-8"><meta name"viewport" content"initial-scale1.0, user-scalableno" /><title></title><link …

【多线程面试题 六】、 如何实现线程同步?

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 面试官&#xff1a; 如何实现线程同步&…

吃豆人C语言开发—Day2 需求分析 流程图 原型图

目录 需求分析 流程图 原型图 主菜单&#xff1a; 设置界面&#xff1a; 地图选择&#xff1a; 游戏界面&#xff1a; 收集完成提示&#xff1a; 游戏胜利界面&#xff1a; 游戏失败界面 死亡提示&#xff1a; 这个项目是我和朋友们一起开发的&#xff0c;在此声明一下…

归并排序(java)

大家好我是苏麟 , 今天说说归并排序 . 归并排序 递归 正式学习归并排序之前&#xff0c;我们得先学习一下递归算法。 定义&#xff1a; 定义方法时&#xff0c;在方法内部调用方法本身&#xff0c;称之为递归. public void show(){System.out.println("aaaa")…

JavaScript_Pig Game切换当前玩家

const current0El document.getElementById(current--0); const current1El document.getElementById(current--1); if (dice ! 1) {currentScore dice;current0El.textContent currentScore;} else {} });这是我们上个文章写的代码&#xff0c;这个代码明显是有问题的&…

Spring Boot进阶(93):体验式教程:手把手教你整合Spring Boot和Zipkin

&#x1f4e3;前言 分布式系统开发中&#xff0c;服务治理是一个比较重要的问题。为了更好地实现服务治理&#xff0c;需要解决服务跟踪问题&#xff0c;即如何对分布式系统中的服务进行监控和追踪。本文将介绍如何使用Zipkin进行服务跟踪&#xff0c;并结合Spring Boot进行整合…

STM32F4X SDIO(一) SD卡介绍

STM32F4X SDIO&#xff08;一&#xff09; SD卡介绍 SD卡分类外观分类容量分类传输速度分类 在之前的章节中&#xff0c;讲过有关嵌入式的存储设备&#xff0c;有用I2C驱动的EEPROM、SPI驱动的FLASH和MCU内部的FLASH&#xff0c;这类存储设备的优点是操作简单&#xff0c;但是缺…