Go语言容器之数组和切片

news2024/9/23 5:18:08
  • Go语言的容器分为值类型和引用数据类型

一、数组

1.数组的声明和初始化

(1) 数组声明的语法

  • var 数组变量名 [数组大小]数组类型

  • 举例:

    package main
    import "fmt"
    
    func main(){
          //数组的声明
          var arr[10]int
    
          //打印数组长度
          fmt.Println("arr的长度为", len(arr))
    
          //数组的赋值
          for i, _ := range arr{
    	       arr[i] = i+1
          }
          fmt.Println("打印数组")
          //打印数组
          for j, w := range arr{
    	      fmt.Println(j, arr[j], w)
          }
     }
    

    结果:
    在这里插入图片描述

  • 在数组的定义中,若在数组长度的位置出现了"…"省略号,即var 数组变量名[…]数组类型,则表示数组的长度是根据初始化值的个数来决定的。

    package main
    import (
    "fmt"
    )
    func main(){
         arr1 := [...]int{}
         arr2 := [...]int{1,2,3,4,5,6,7,8,9}
    
         fmt.Println("打印arr1:")
         for i, _ := range arr1{
    	     fmt.Println(arr1[i])
         }
         fmt.Println("打印arr2:")
         for i, _ := range arr2{
    	     fmt.Println(arr2[i])
         }
         fmt.Printf("arr1的类型为%T:\n",arr1)
         fmt.Printf("arr2的类型为%T:\n",arr2)
    }
    

    结果:在这里插入图片描述

(2) 比较两个数组是否相等

package main

import "fmt"

func main(){
	arr1 := [5]int{1,2,3,4,5}
	arr2 := [...]int{1,2,3,4,5}
	arr3 := [5]int{0,1,2,3,4}


	fmt.Printf("arr1==arr2?的结果%v\n",arr1 == arr2)
	fmt.Printf("arr1==arr3?的结果%v\n",arr1 == arr3)
}

结果:
在这里插入图片描述

2.多维数组

  • 多维数组的语法:var 数组变量名[size1][size2]…[sizen]数组类型

(1) 声明二维数组

package main
import "fmt"

func main(){
	var arr1[4][3]int//声明一个多维数组,大小为4,3
	arr2 := [4][3]int{{0,1,2},{1,2,3},{2,3,4},{3,4,5}}//声明数组并初始化所有元素
	arr3 := [4][3]int{1:{0,1,2},2:{1,2,3}}//声明并初始化数组中指定索引的元素
	arr4 := [4][3]int{1:{0:20},2:{2:30}}//声明并初始化数组中指定元素

	for i,v := range arr1{
		fmt.Printf("arr1的结果:")
		fmt.Println(v)
		fmt.Printf("arr2的结果:")
		fmt.Println(arr2[i])
		fmt.Printf("arr3的结果:")
		fmt.Println(arr3[i])
		fmt.Printf("arr4的结果:")
		fmt.Println(arr4[i])
	}
}

结果:
在这里插入图片描述

(2) 数组赋值

package main

import "fmt"

func main(){
	var arr1[2][2]int
	var arr2[2][2]int

	for i,_ := range arr2{
		for j, _ := range arr2[i]{
			arr2[i][j] = i + 1
		}
	}

	arr1 = arr2
	arr2[0][1] = 10
	arr2[1][1] = 20
	for i,v := range arr1{
		fmt.Printf("arr1的值为:")
		fmt.Println(v)
		fmt.Printf("arr2的值为:")
		fmt.Println(arr2[i])
	}
}

结果:在这里插入图片描述

二、切片

1.切片概述

  • slice切片就是数组中一段连续的片段的引用。故切片是个引用类型
  • 从数组或者切片生成新的切片:slice[开始位置 : 结束位置]
  • 从数组或者切片中生成新的切片拥有如下特征:
    (1)取出的元素数量为:结束位置 - 开始位置
    (2)取出的元素不包含结束位置对应的索引(左闭右开)。切片最后一个元素是slice[len(slice)]
    (3)当缺省开始位置时,表示从连续区域开头位置到切片结束位置
    (4)当缺省结束位置时,表示从切片开始位置到连续区域末尾位置
    (5)当开始位置和结束位置都缺省时,表示从连续区域开头位置到连续区域末尾位置,即整个连续区域。即表示原有的切片
    (6)当开始位置和结束位置两者都为0时,即空切片。一般用于切片复位
  • 切片举例:
    package main
    
    import "fmt"
    
    func main(){
    	arr := [10]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
    	fmt.Println("数组arr的值为",arr)
    	fmt.Println("切片arr[0:1]的值为", arr[0:1])
    	fmt.Println("切片arr[2:8]的值为", arr[2:8])
    	fmt.Println("切片arr[4:9]的值为", arr[4:9])
    	fmt.Println("切片arr[5:10]的值为", arr[5:10])
        fmt.Println("切片arr[5:10]中元素个数为", len(arr[5:10]))
        fmt.Println("切片最后一个元素arr[len(arr)]的值为",arr[len(arr[4:9])])
        fmt.Println("切片arr[2:]的值为",arr[2:])
        fmt.Println("切片arr[:8]的值为",arr[:8])
        fmt.Println("切片arr[:]的值为",arr[:])
    }
    
    结果:通过结果可以看见,是左闭右开的。在这里插入图片描述
  • 声明新切片的语法:var 切片名[]切片类型
    package main
    
    import "fmt"
    
    func main() {
    	var strSlice []string //声明字符串切片
    	var intSlice []int    //声明整型切片
    	var emptySlice []int
    	{
    	} //声明一个空切片
    
    	fmt.Println(strSlice, intSlice, emptySlice)
    	fmt.Println("len(strSlice)=", len(strSlice))
    	fmt.Println("len(intSlice)=", len(intSlice))
    	fmt.Println("len(emptySlice)=", len(emptySlice))
    	fmt.Println("strSlice == nil ? =", strSlice == nil)
    	fmt.Println("intSlice == nil ? =", intSlice == nil)
    	fmt.Println("emptySlice == nil ? =", emptySlice == nil)
    }
    
    结果:
    在这里插入图片描述

2.make动态构造切片

  • 若需要动态创建一个切片,则可以使用make()内建函数:make([]切片类型,切片大小,切片容量)
  • 注意:使用make()函数生成的切片一定发生了内存分配操作,但给定开始与结束位置(包括切片复位)的切片结果指向已经分配好的区域。设定开始与结束位置不会发生内存分配操作。
    package main
    import "fmt"
    
    func main() {
    	slice1 := make([]int, 2, 20)//slice1切片的大小为2,容量为20
    	slice2 := make([]int, 2)//slice2切片的大小为2
    	//slice1和slice2都是预分配了2个元素的切片,只是slice1内部存储空间已经分配了20个,但实际只用了2个
    
    	fmt.Println("slice1:",slice1)
    	fmt.Println("slice2:",slice2)
    	fmt.Println("len(slice1):",len(slice1))
    	fmt.Println("len(slice2):",len(slice2))
    }
    
    结果:在这里插入图片描述

3.在切片中添加元素

  • 切片的len元素个数并不等于切片的cap容量大小,cap容量扩容是2倍进行扩容的
    package main
    
    import "fmt"
    
    func main() {
    	var slice1 []int
    	for i:=0; i<20; i++{
    		slice1 = append(slice1, i)
    		fmt.Printf("len:%d, cap:%d, pointer:%p\n", len(slice1), cap(slice1), slice1)
    	}
    }
    
    结果:
    在这里插入图片描述

4.切片复制copy

  • copy(目标切片, 原切片)
    package main
    
    import "fmt"
    
    func main() {
    	arr := [10]int{0,1,2,3,4,5,6,7,8,9}
    
    	slice1 := arr[2:9]
    	slice2 := []int{10,11,12,13}
    
    	fmt.Println("复制前:")
    	fmt.Println("slice1=",slice1)
    	fmt.Println("slice2=",slice2)
    	cp1 := copy(slice1,slice2)//将slice2的所有元素复制到slice1
    	cp2 := copy(slice2,slice1)//将slice1中前几个元素复制到slice2中
    	fmt.Println("复制后:")
    	fmt.Println("slice1=",slice1)
    	fmt.Println("slice2=",slice2)
    	fmt.Println("cp1复制的总数为:", cp1)
    	fmt.Println("cp2复制的总数为:", cp2)
    }
    
    结果:
    在这里插入图片描述

5.range关键字循环切片

package main
import "fmt"

func main() {
	arr := [10]int{0,1,2,3,4,5,6,7,8,9}
	slice1 := arr[2:9]
	for i,v:=range slice1{
		fmt.Printf("index:%d, value:%d\n", i, v)
	}
}

结果:
在这里插入图片描述

6.多维切片

  • 声明方法:var 切片名 [][]…[]切片类型
package main

import "fmt"

func main() {
	var slice1 [][]int
	slice1 = [][]int{{0,1},{10,11},{20}}
	fmt.Println("添加元素前:")
	for i,v:=range slice1{
		fmt.Printf("index:%d, value:%d\n", i, v)
	}

	slice1[2] = append(slice1[2], 100)//为第三个切片添加值为100的元素
	fmt.Println("添加元素后:")
	for i,v:=range slice1{
		fmt.Printf("index:%d, value:%d\n", i, v)
	}
}

结果:
在这里插入图片描述

三、数组和切片的区别

  • 数组是数值类型,切片是引用类型
  • 数组的长度是固定的,切片的长度不固定,切片是动态的数组
  • 数组只有长度的概念,切片还有容量(cap)的概念
  • 切片的底层是数组
  • 数组之间可以通过"=="比较,判断两个数组是否有相同元素,但是切片不行,只能和nil进行相等判断
  • 一个零值的切片等于nil,一个nil值的切片并没有底层数组
  • 数组传递给函数的时候,是需要先拷贝再传递;而切片是引用传递,函数内可以直接修改切片的内容

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

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

相关文章

《Java高并发核心编程. 卷1, NIO、Netty、Redis、ZooKeeper》 读书笔记

第2章 高并发IO的底层原理 2.1 IO读写的基本原理 为了避免用户进程直接操作内核&#xff0c;保证内核安全&#xff0c;操作系统将内存&#xff08;虚拟内存&#xff09;划分为两部分&#xff1a;一部分是内核空间&#xff08;Kernel-Space&#xff09;&#xff0c;另一部分…

Ubantu docker学习笔记(二)拉取构建,属于你的容器

文章目录一、拉取启动容器二、本地镜像初解三、构建镜像3.1使用docker commit构建镜像切换阿里镜像3.2使用dockerfile构建镜像四、总个结吧这里的话&#xff0c;就详细说说小唐对于容器的配置&#xff0c;对了&#xff01;小唐参考的书籍是Linux容器云实战&#xff01;&#xf…

做更好的自己!NAS部署wiki.js现代化知识管理工具,让知识上云!

知识管理是一个永恒的课题&#xff0c;各种方法、工具层出不穷。老Q这么多年也体验过了非常多的工具&#xff0c;这几年来&#xff0c;老Q使用的工具逐步从付费迁移到开源&#xff0c;从公有云迁移到私有云。前者是为了折&#xff08;SHENG&#xff09;腾 &#xff08;QIAN&…

红黑树的介绍和实现

文章目录1. 红黑树1.1 红黑树的概念1.2 红黑树的性质1.3 红黑树节点的定义1.4 红黑树的插入1.5 红黑树的验证1.6 红黑树与AVL树的比较1. 红黑树 1.1 红黑树的概念 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但在每个结点上增加一个存储位表示结点的颜色&#xff0c;可以…

linux 内存泄露检测工具-Valgrind的使用

Valgrind是一款用于内存调试、内存泄漏检测以及性能分析的软件开发工具。安装,我是先valgrind一下发现这个的版本apt install valgrind # version 1:3.15.0-1ubuntu9.1新建一个项目与添加一个main.c编辑main.c的代码:#include <stdio.h> /*标准输入输出定义*/ #incl…

springcloud3 GateWay

一 GateWay 1.1 GateWay的作用 gateway相当于所有服务的门户&#xff0c;将客户端请求与服务端应用相分离&#xff0c;客户端请求通过gateway后由定义的路由和断言进行转发&#xff0c;路由代表需要转发请求的地址&#xff0c;断言相当于请求这些地址时所满足的条件&#xff…

Mybatis中的一级缓存和二级缓存

Mybatis作为一款强大的ORM框架&#xff0c;其中也用到了缓存来加速查询&#xff0c;今天我们一起来探讨下。 Mybatis可以使用懒加载来提高查询的效率&#xff0c;并且可以通过缓存来提高查询的效率。其中包括有一级缓存和二级缓存。 一级缓存是sqlSession级别的缓存&#xff0c…

怎么给电脑分盘与合并磁盘?教你三招

电脑只有一个C盘&#xff0c;想要再分出一个或多个分区&#xff0c;怎么办&#xff1f;电脑C盘的容量太小&#xff0c;太容易满了&#xff0c;想重新分盘&#xff0c;或者把其他盘跟它合并&#xff0c;但因为文件太多备份实在是太麻烦&#xff0c;怎么办&#xff1f;怎么给电脑…

tomcat 启动时卡住问题排查

正常项目无法访问&#xff08;Linux 服务器&#xff09;&#xff0c;启动tomcat时卡在下图位置&#xff0c;项目无法启动。 1、先检查tomcat日志、项目日志没有报错信息&#xff0c;且没再产生新的日志信息。 2、jdk、tomcat 、 jvm 配置&#xff0c;服务器环境、内存、存储没…

论文阅读:Adversarial Cross-Modal Retrieval对抗式跨模式检索

Adversarial Cross-Modal Retrieval 对抗式跨模式检索 跨模态检索研究的核心是学习一个共同的子空间&#xff0c;不同模态的数据可以直接相互比较。本文提出了一种新的对抗性跨模态检索&#xff08;ACMR&#xff09;方法&#xff0c;它在对抗性学习的基础上寻求有效的共同子空间…

JVM学习笔记九:对象实例化与直接内存

0. 前言 声明&#xff1a; 感谢尚硅谷宋红康老师的讲授。 感谢广大网友共享的笔记内容。 B站&#xff1a;https://www.bilibili.com/video/BV1PJ411n7xZ 本文的内容基本来源于宋老师的课件&#xff0c;其中有一些其他同学共享的内容&#xff0c;也有一些自己的理解内容。 1. …

一文解码:如何在人工智能热潮下实现产业“智”变

近期由ChatGPT有关人工智能的话题引发了全民热议&#xff0c;在这股子浪潮下&#xff0c;讨论最多的话题就是ChatGPT的出现会为我们带来怎样的技术变革&#xff1f;是否会改变我们目前的生产方式&#xff1f;对于未来人工智能技术的发展&#xff0c;我们该如何客观看待&#xf…

Unity Lighting -- 使用Light Probes

什么是动态物体&#xff08;dynamic objects&#xff09; 到目前为止的例子中&#xff0c;我们场景中的所有东西都是静止的。但在实际的游戏或实时应用中&#xff0c;场景中有移动的物体很正常&#xff0c;比如走动的人或动物&#xff0c;汽车&#xff0c;飞机等&#xff0c;它…

MRCP在美团语音交互中的实践和应用

当你和智能语音机器人对话交互时&#xff0c;你是否好奇电话背后的机器人如何“听懂”你的意思&#xff0c;又如何像人一样“回答”你的问题&#xff1f;其中比较重要的技术就是 MRCP。本文主要介绍了 MRCP 在美团语音交互中的实践和应用&#xff0c;基于美团自研的语音识别及语…

动态规划入门经典问题讲解

最近开始接触动态规划问题&#xff0c;以下浅谈&#xff08;或回顾&#xff09;一下这些问题的求解过程。解题思路对于动态规划问题&#xff0c;由于最终问题的求解需要以同类子问题作为基础&#xff0c;故需要定义一个dp数组&#xff08;一维或二维&#xff09;来记录问题求解…

Vue 3.0 单文件组件 【Vue3 从零开始】

#介绍 在很多 Vue 项目中&#xff0c;我们使用 app.component 来定义全局组件&#xff0c;紧接着用 app.mount(#app) 在每个页面内指定一个容器元素。 这种方式在很多中小规模的项目中运作的很好&#xff0c;在这些项目里 JavaScript 只被用来加强特定的视图。但当在更复杂的…

[Java·算法·中等]LeetCode39. 组合总和

每天一题&#xff0c;防止痴呆题目示例分析思路1题解1分析思路2题解2&#x1f449;️ 力扣原文 题目 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target &#xff0c;找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 &#xff0c;并以列表形…

Golang Map实现原理分析与解读

一、map的结构与设计原理 golang中map是一个kv对集合。底层使用hash table&#xff0c;用链表来解决冲突 &#xff0c;出现冲突时&#xff0c;不是每一个key都申请一个结构通过链表串起来&#xff0c;而是以bmap为最小粒度挂载&#xff0c;一个bmap可以放8个kv。在哈希函数的选…

配置临时SSL子域名泛化证书

配置临时SSL子域名泛化证书 三个月有效期第一步&#xff1a;访问SSL证书地址第二步&#xff1a;在华为云上/其他服务器上搜索DNS云解析服务类似的功能第三步&#xff1a;将SSL申请的信息添加到服务器的记录集中第四步&#xff1a;添加完信息进行保存获取key / crt第五步&#x…

蓝桥冲刺31天之第七天

目录 A&#xff1a;三角回文数 B&#xff1a;数数 C&#xff1a;数组切分 D&#xff1a;倍数问题 一星陨落&#xff0c;黯淡不了星空灿烂&#xff1b; 一花凋零&#xff0c;荒芜不了整个春天。 如果命运是世界上最烂的编剧&#xff0c; 你就要争取做人生最好的演员。 即使生…