Go基础编程 - 05 - 数组与切片

目录

    • 1. 数组
    • 2. 切片
      • 2.1. slice 声明、初始化
      • 2.2. slice 操作
      • 2.3. append() 追加切片、扩容
      • 2.4. 字符串和切片
    • 3. Copy
    • 4. Array、Slice 内存布局

上一篇:基本类型、常量和变量

下一篇:指针


1. 数组

数组是同一种类型固定长度的序列(有长度、类型构成)。一但定义,长度不可改变。

  • 数组为值类型,赋值和传参会复制整个数组,而不是指针。
  • 数组声明时,必须固定长度;长度是数组类型的一部分,不同长度的数组类型表示不同的类型([2]int[3]int 为不同的数组类型);
  • 数组未赋值,则初始化为类型缺省值(零值)。
  • 内置函数lencap都返回数组长度。
  • 越界访问产生panic。
  • 指针数组:[n]*T,数组指针:*[n]T
  • 值拷贝行为会造成性能问题,通常会建议使用 slice,或数组指针。
package mainimport ("fmt""reflect"
)func main() {// 初始化var arr1 [5]intvar arr2 = [5]int{0, 1, 2, 3, 4}var arr3 = [3]int{0, 2: 4}var arr4 = [...]int{1, 2, 3}fmt.Println(arr1, arr2, arr3, arr4)// 长度是数组类型的一部分,不同长度的数组类型为不同类型if reflect.TypeOf(arr1) == reflect.TypeOf(arr2) {fmt.Println("arr1 和 arr2 数据类型相同!")}if reflect.TypeOf(arr1) != reflect.TypeOf(arr3) {fmt.Println("arr1 和 arr3 数据类型不相同!")}// 数组为值类型:赋值和传参复制整个数组arr1copy := arr1arr1copy[0] = 10fmt.Println(arr1, arr1copy)// 值拷贝行为会造成性能问题,通常会建议使用 slice,或数组指针。fn := func(arr [5]int) {arr[1] = 20}fn(arr1)fmt.Println(arr1)// 指针数组:[n]*Tvar pa = [2]*int{new(int)}*pa[0] = 10pa[1] = new(int) // 引用类型必须先分配内存,须使用new分配内存*pa[1] = 20      // 若不分配内存(注释上一行代码),则产生panic: runtime error: invalid memory address or nil pointer dereferencefmt.Printf("pa:%v  \n", pa)// 数组指针:*[n]Tvar ap *[3]int // var ap = new([3]int)ap = new([3]int)*ap = [3]int{4, 5, 6}fmt.Printf("ap:%v  psr:%p  type:%T  \n", *ap, ap, ap)// 多维数组multArr := [...][2]int{{0, 0}, {1, 1}, {2, 2}}fmt.Println(multArr)
}

2. 切片

切片并不是数组或数组指针。它通过内部指针和相关属性引用数组片段,以实现变长方案。

  • 切片是引用类型;底层数据结构是一个数组,可以看作是对数组某个连续片段的引用。
  • 切片是可变长的(包含长度、容量)。
  • 长度:用len()函数求长度,表示可用元素数量,读写操作不能超过该限制。
  • 容量:用cap()函数求最大容量,为切片底层数组的长度。
  • 扩容及规律: 扩容通常以 2 倍容量重新分配底层数组;当原有切片容量大于 1024 时,以 1.25 倍扩容。
  • 若 slice == nil,则 lencap结果都等于 0。

2.1. slice 声明、初始化

package mainimport "fmt"func main() {// 声明var s []int     if s == nil {fmt.Println("s is nil")}s1 := []int{1, 2, 3, 4}// 使用 make()var s2 []int = make([]int, 0)s3 := make([]int, 5)s4 := make([]int, 5, 8)fmt.Println(s, s1, s2, s3, s4)fmt.Println("Cap:", cap(s), cap(s1), cap(s2), cap(s3), cap(s4))// 从数组切片arr := [5]int{1, 2, 3, 4, 5}var s5 []ints5 = arr[1:4] // 前包后不包fmt.Println(s5, len(s5), cap(s5))
}

2.2. slice 操作

  • slice 的索引起点为 0。
  • 切片截取:s[i:j:max],满足 i <= j <= max;其中,i为起始索引(包含),省略值 0j结束索引(不包含),省略值len(s)max为截取最大索引,省略值len(s)
  • 截取新切片长度 = j - i
  • 截取新切片容量 = max - i
  • 截取新切片开始索引非 0,指针地址指向底层数组中新切片开始索引所在的地址;起始地址相同的slice指针地址相同,例:s[i], s[i:], s[i:j], s[i:j:max] 的指针引用地址都相同。
package mainimport "fmt"func main() {s := [...]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}v := s[0]fmt.Println(v)s1 := s[2:5]s2 := s[2:8]s3 := s[:10:12]fmt.Println("val", v, s1, s2, s3)fmt.Println("len", len(s1), len(s2), len(s3))fmt.Println("cap", cap(s1), cap(s2), cap(s3))fmt.Printf("prs %p %p %p \n", s1, s2, s3)
}

2.3. append() 追加切片、扩容

append() 向 slice 尾部添加数据,返回新的 slice 对象。

扩容通常以 2 倍容量重新分配底层数组。在大批量添加数据时,建议一次性分配足够大的空间,以减少内存分配和数据复制开销。或初始化足够长的 len 属性,改用索引号进行操作。及时释放不再使用的 slice 对象,避免持有过期数组,造成 GC 无法回收。

package mainimport "fmt"func main() {arr := []int{0, 1, 2, 3, 4}fmt.Println("len =", len(arr), "cap =", cap(arr))       // len = 5  cap = 5arr1 := append(arr, 5)       // 追加数据,超出原切片容量,则进行扩容fmt.Println("len =", len(arr1), "cap =", cap(arr1))     // len = 6  cap = 10fmt.Printf("prs: %p %p \n", arr, arr1)  // 对比底层数组起始指针,扩容后重新分配底层数组,与原数组无关。arr1 = append(arr1, []int{6, 7, 8, 9, 10}...)fmt.Println("len =", len(arr1), "cap =", cap(arr1))     // len = 11 cap = 20
}

2.4. 字符串和切片

string 底层就是一个 byte/rune 的数组,因此,也可以进行切片操作。

package mainimport "fmt"func main() {str := "Hello, Chain"s1 := str[:5]println(s1) // Hello//string 本身是不可变的,因此要改变string中字符;需将字符转为slice,进行更改,再转为string//str[0] = 'X'     // 报错:cannot assign to str[0] (value of type byte)s := []byte(str) // 英文字符使用 byte,代表ASCII码的一个字符// 赋值需要使用单引号(''),单引号定义一个字符,双引号定义个字符串s = append(s, '!')str = string(s)fmt.Println(str)str2 := "你好,中国"s2 := []rune(str2) // 包含中文字符使用 rune,代表一个UTF-8字符s2[3] = '伟's2[4] = '大's2 = append(s2, []rune{'的', '中', '国'}...)fmt.Println(string(s2))
}

3. Copy

  • 深拷贝:拷贝的是数据本身;值类型数据,默认是深拷贝,Array、Int、Sting、Struct、Bool、Float。
  • 浅拷贝:拷贝的是数据地址;引用类型数据,默认浅拷贝,Map、Slice。
package mainimport "fmt"func main() {arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}arr2 := arrarr[1] = 10fmt.Println(arr, arr2)fmt.Printf("prs: %p %p \n", &arr, &arr2) // Array 属于深copyfmt.Println()s1 := arr[:6]s2 := arr[4:]s1[5] = 50 // Slice 属于浅copyfmt.Println(s1, s2)fmt.Printf("prs:%p %p \n", s1, s2)// copy函数只能用于切片,属于浅拷贝;允许元素区间重叠copy(s1, s2)s1[1] = 100fmt.Println(s1, s2, arr)
}

4. Array、Slice 内存布局


array-slice

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

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

相关文章

工业 web4.0 的 UI 风格,独树一帜

工业 web4.0 的 UI 风格&#xff0c;独树一帜

[深度学习]基于C++和onnxruntime部署yolov10的onnx模型

基于C和ONNX Runtime部署YOLOv10的ONNX模型&#xff0c;可以遵循以下步骤&#xff1a; 准备环境&#xff1a;首先&#xff0c;确保已经下载后指定版本opencv和onnruntime的C库。 模型转换&#xff1a;按照官方源码&#xff1a;https://github.com/THU-MIG/yolov10 安装好yolov…

【计算机网络】TCP报文详解

认识TCP报头 其实协议的形式都是一个结构化的数据&#xff0c;TCP协议也不例外。一起来看看TCP协议的报头是怎么样的。 以上就是TCP报头&#xff0c;实际上是一个结构化的数据&#xff0c;也就是一个结构体。例如&#xff1a; struct tcp_hdr {unsigned int stc_port : 16;un…

光储充一体化,开启绿色出行新篇章

一、追光逐梦&#xff0c;绿色能源点亮未来 在蔚蓝的天空下&#xff0c;光伏发电板如同一片片金色的叶子&#xff0c;静静地捕捉着太阳的光芒。它们不仅为大地带来光明&#xff0c;更是绿色出行的强大后盾。光储充一体化充电站&#xff0c;以光伏为源&#xff0c;储能为桥&…

Kubernetes集群部署Prometheus和Grafana

目录 一、部署Node-Exporter 二、Prometheus安装和配置 1.创建账号并予以授权 2.创建存储卷存储Prometheus配置信息 3.通过Deployment方式部署Prometheus 4.创建Service 三、Prometheus配置热加载 四、Grafana安装 五、K8s部署Kube-State-Metrics 1.创建Kube-State-M…

C#开发-集合使用和技巧(一)常用集合和方法介绍

C#开发-集合使用和技巧 &#xff08;一&#xff09;常用集合和方法介绍常用集合和方法介绍 C#开发-集合使用和技巧1. 集合基础集合介绍集合跟数组对比 2.我们常用的集合类型列表List<T>键值对集合Dictionary<TKey,TValue>队列Queue<T>其他一些集合类型堆栈St…

架构设计 - MySQL 插入数据性能优化策略

mysql 数据库提高数据插入效率主要可以考虑以下方面&#xff1a; 使用批量插入数据的 SQL 语句&#xff0c;避免使用 for 循环逐条记录插入。 所有插入语句共用一个事务&#xff0c;避免1条SQL语句开1个事务&#xff0c;所有操作都完成后再提交事务。 尽量按照索引递增顺序插入…

Apache Doris单机快速安装(已踩坑)

官方文档&#xff1a;https://doris.incubator.apache.org/zh-CN/docs/get-starting/quick-start/ 环境&#xff1a; 操作系统&#xff1a;CentOS7.6 X86_64 JDK&#xff1a;Oracle jdk1.8.0_351 1.版本下载 从 doris.apache.org 下载相应的 Doris 安装包&#xff0c;并且解压…

Springboot防疫知识科普系统-计算机毕业设计源码03531

摘 要 如今计算机行业的发展极为快速&#xff0c;搭载于计算机软件运行的数据库管理系统在各行各业得到了广泛的运用&#xff0c;其在数据管理方面具有的准确性和高效性为大中小企业的日常运营提供了巨大的帮助。自从2020年新冠疫情爆发以来&#xff0c;防疫成了社会关注的重中…

RK3568技术笔记七 安装Ubuntu Linux

在新弹出的窗口中&#xff0c;单击“CD/DVD &#xff08;SATA&#xff09;”。如下图所示&#xff1a; 在右侧选择“使用ISO映像文件”。然后单击“浏览”&#xff0c;找到SAIL-RK3568开发板光盘->通用工具->虚拟机Ubuntu->ubuntu-18.04.4-desktop-amd64.iso。最后点击…

探索Vue.js中的文件夹上传解决方案:vue-simple-uploader

在现代Web应用开发中&#xff0c;文件上传是一个常见需求。然而&#xff0c;随着应用复杂性的增加&#xff0c;传统的文件上传方式可能无法满足所有需求&#xff0c;特别是当涉及到文件夹上传和大文件处理时。本文将介绍一个基于Vue.js的解决方案——vue-simple-uploader&#…

MES系统助力制造业数字化转型

一、MES系统的定义和功能 MES&#xff08;Manufacturing Execution System&#xff09;即制造执行系统&#xff0c;是一种可层级化管理生产活动的软件系统。它可以实现对生产过程全面的监控、调度、控制和优化&#xff0c;提高生产的效率、质量和安全性。MES系统具有以下几个主…

最新区块链论文速读--CCF A会议 ICSE 2024 共13篇 附pdf下载 (2/2)

Conference&#xff1a;International Conference on Software Engineering (ICSE) CCF level&#xff1a;CCF A Categories&#xff1a;Software Engineering/System Software/Programming Languages Year&#xff1a;2024 Num&#xff1a;13 第1~7篇区块链文章请点击此处…

电脑技巧:认识全能绘画软件Krita

目录 一、软件简介 二、软件功能 2.1 强大的画笔引擎 2.2专业色彩管理 2.3 多层编辑与管理 2.4 动画制作 三、软件特点 四、安装说明 五、使用技巧 六、快捷键大全 对于喜欢绘画的朋友来说&#xff0c;Krita 是一款不可多得的绘画工具&#xff0c;它具有开源、免费、…

RedHat9 | Mariadb数据库的配置与管理

一、实验环境 1、Mariadb数据库介绍 MariaDB数据库管理系统是一个开源的关系型数据库管理系统&#xff0c;与MySQL高度兼容&#xff0c;并提供了更多的功能和性能优化。 起源和背景 MariaDB是MySQL的一个分支&#xff0c;主要由开源社区维护。由MySQL的创始人Michael Widen…

体验亚马逊AIGC——Amazon Bedrock

前言 随着人工智能技术的不断发展&#xff0c;我们已经进入了一个全新的时代&#xff0c;即AI驱动的时代。在这个时代&#xff0c;人工智能已经逐渐成为我们生活中不可或缺的一部分&#xff0c;它可以帮助我们更好地处理各种复杂的问题&#xff0c;提高我们的工作效率&#xff…

UDP的组播发送与接收C语言测试和nc接收组播测试

组播这个东西&#xff0c;很多年前用过一次。本身的原理不复杂&#xff0c;未知的是使用的环境&#xff0c;受使用环境的影响有多大&#xff0c;还是那句废话&#xff0c;具体问题具体分析。 发送端代码multicast.c #include <stdio.h> #include <stdlib.h> #…

鸿蒙开发:【设置任务快照的图标和名称】

设置任务快照的图标和名称 设置任务快照的图标和名称是为了提高用户界面的可视化性和用户体验&#xff0c;以便更好地管理和跟踪应用程序中的任务和功能。通过为每个任务快照设置不同的图标和名称&#xff0c;可以更轻松地区分和识别每个任务的功能。 默认情况下任务快照的图…

C++基础知识(八:STL标准库 Map和multimap )

Map C 标准模板库&#xff08;STL&#xff09;中的 map 容器是一种非常有用的关联容器&#xff0c;用于存储键值对&#xff08;key-value pairs&#xff09;。在 map 中&#xff0c;每个元素都由一个键和一个值组成&#xff0c;其中键是唯一的&#xff0c;而值则可以重复。 基…

mybatis中resultMap和resultType的区别

总结 基本映射 &#xff1a;&#xff08;resultType&#xff09;使用resultType进行输出映射&#xff0c;只有查询出来的列名和pojo中的属性名一致&#xff0c;该列才可以映射成功。&#xff08;数据库&#xff0c;实体&#xff0c;查询字段,这些全部都得一一对应&#xff09;…