Go语言的内置容器

news2024/11/14 2:31:40

文章目录

  • 一、数组
      • 数组的定义
      • 数组声明
      • 数组特点
      • 数组元素修改
  • 二、切片
      • 切片声明
      • 基于数组创建切片
      • 使用make()函数构造切片
      • 使用append()为切片动态添加元素\
      • 使用copy()复制新的切片
      • 数组与切片相互转换
  • 三、Map映射
      • Map定义
      • 使用make()函数创建map
      • 用切片作为map的值
      • 使用delete()函数删除元素

一、数组

数组的定义

一个由固定长度的特定元素组成的序列

数组声明

标准格式声明数组:

var variable_name [size]type

初始化数组:

var variable_name = [size]type{value,...}

编译器自行推断数组大小:

var variable_name = [...]type {value,...}

一些示例:

//示例1
var a [3] int  //声明一个数组为 a ,类型为int,大小为3的数组
a[0] = 12 //为第一个元素填充数据,为12
a[1] = 13 //为第二个元素填充数据,为13
a[2] = 14 //为第三个元素填充数据,为14

//示例2
var a = [3] int {12,13,14} //定义且声明数组内容


//示例3
a := [3]int {12,13,14}//定义且声明数组内容

//示例4
a := [3]int{12}//可以只填充部分数据

//示例5
a := [3]int {1:13,2:14}//填充指定位置

//示例6
a := [...]int{12,13,14}//编译器自行判断数组长度

数组特点

  • 数组的每个元素可以通过索引下标来访问
  • 索引下标的范围从0开始到数据长度减1结束
  • 数组无法灵活扩容:在定义数组元素数量后,赋值元素变量个数必须要小于或者等于预设值的元素数量
  • type指任意的基本类型,也可以是数组本身,实现多维数组
  • 在Go语言中数组是值类型而不是引用类型
  • 这意味着当数组变量被赋值时,将会获得原数组的拷贝,新数组中元素的改变不会影响原数组中元素的值

示例:

package main
import "fmt"
func main() {
    a := [...]int{12, 78, 50}
    b := a	// 将a数组复制给b数组
    b[0] = 60
    fmt.Println(a)
    fmt.Println(b)
}

//运行结果为:
//[12 78 50]
//[60 78 50]

数组元素修改

package main
import "fmt"
func main() {
	var a [1]string                          //定义一个1个元素的string类型数组,string默认值为空
	var b = [2]string{“a”, “b”}  //定义一个2个元素的string类型数组
	c := [3]string{"a", "b", "c"}         //定义并初始化一个3个空间的string类型数组
	d := [...]string{"a", "b", "c", "d"} //自动推到元素个数
	e := d                                        //拷贝数组
	e[0] = "e"                                  //修改数组指定位置的值
	fmt.Println(a, len(a))                 //打印a数组、a数组长度
	fmt.Println(b)
	fmt.Println(c)
	fmt.Println(d, len(d))
	fmt.Println(e, len(e))
}



//运行结果为:
//[] 1
//[a b]
//[a b c]
//[a b c d] 4
//[e b c d] 4

二、切片

数组和切片的对比
在这里插入图片描述

切片声明

切片声明:

var name[]type = []type{......}

切片特点:

  • []中不需要指定长度,即长度是不固定的
  • 可以追加元素,在追加时可能使切片的容量增大,可以从数据中生成新的切片或者是声明新的切片

示例:

package main
import "fmt"
func main() {
    var a []int= []int{10,11,12,13}
    fmt.Println(a,len(a))
}



//运行结果为:
//[10 11 12 13] 4

基于数组创建切片

var name [] type = 数组名[开始位置:结束位置]

特点:

  • 结束位置的元素不取
  • 切片数量 = 结束位置下标 - 开始位置下标
  • 当缺省开始位置时,表示从连续的区域开头到结束位置
    在编程和数据处理领域,"缺省"(或“默认”)通常指的是在没有明确指定某个值或选项时,系统或程序将自动采用的一个预设值或行为。这个预设值或行为被称为“缺省值”或“默认值”。
  • 当缺省结束位置时,表示从开始位置到整个连续区域末尾
  • 两者同时缺省时,与数组本身等效
  • 两者同时为0时,等于空切片,一般用于切片复位

示例:


//示例1
package main
import "fmt"
func main() {
    a := [5]string{"A","B","C","D"}
    var b []string = a[1:2]
    fmt.Println(a)
    fmt.Println(b,len(b))
}


//运行结果为:
//[A B C D ]
//[B] 1


//示例2
package main
import "fmt"
func main() {
    a := [5]int{76, 77, 78, 79, 80}
    var b []int = a[1:3]	//取a数组的第1到第3个元素
    var c []int = a[:3]	//取a数组的第0到第3个元素
    var d []int = a[1:]	//取a数组的第1到最后一个元素
    var e []int = a[:]	//取a数组的第0到最后一个元素
    var f []int = a[0:0]	//空切片
    fmt.Println(a,len(a))
    fmt.Println(b,len(b))
    fmt.Println(c,len(c))
    fmt.Println(d,len(d))
    fmt.Println(e,len(e))
    fmt.Println(f,len(f))
}



//运行结果为:
//[76 77 78 79 80] 5
//[77 78] 2
//[76 77 78] 3
//[77 78 79 80] 4
//[76 77 78 79 80] 5
//[] 0

  • 切片本身不包含任何数据
  • 切片是底层数组的一个上层表示
  • 对切片进行的任何修改都将反映在底层数据化中
package main
import "fmt"
func main() {
    a := [5]string{"A","B","C","D","E"}
    var b []string = a[1:3]
    fmt.Println("修改前的a数组:",a)
    fmt.Println("修改前的b切片:",b)
    b[1]="2"
    fmt.Println("修改后的a数组:",a)
    fmt.Println("修改后的b切片:",b)
}



//运行结果为:
//修改前的a数组: [A B C D E]
//修改前的b切片: [B C]
//修改后的a数组: [A B 2 D E]
//修改后的b切片: [B 2]

  • 切片的长度是指切片中元素的个数
  • 切片的容量是指从切片的起始元素开始到其底层数组中的最后一个元素的个数
  • 切片的长度可以动态的改变(最大为其容量)
  • 任何超出最大容量的操作都会发生运行时错误
package main
import (
    "fmt"
)
func main() {
    a := [...]string{"A", "B", "C", "D", "E"}
    b := a[1:3]
    fmt.Printf("数组a长度为:%d \n切片b容量为:%d", len(a), cap(b))
}



//运行结果为:
//数组a长度为:5 
//切片b容量为:4

使用make()函数构造切片

var name [] type = make([]type,size,cap)

特点:

  • type指切片元素类型
  • size 指的是为这个类型分配多少个元素
  • cap 为预分配的元素数量
  • cap设定后不会影响 size,只是为了提前分配空间,降低多次分配空间造成的性能问题
package main
import "fmt"
func main() {
    var a [] int =make([]int,5,10)
//创建一个切片,初始元素个数为5,并预留10个元素的存储空间
    a[0]=10
    a[4]=14
    fmt.Println("切片内容:", a)
    fmt.Println("切片长度:", len(a))
    fmt.Println("切片容量:", cap(a))
}



//运行结果为:
//切片内容: [10 0 0 0 14]
//切片长度: 5
//切片容量: 10

使用append()为切片动态添加元素\

append(name,value)
append(name,[]type[value,value,value]...)

特点:

  • 可以为切片追加单个或多个元素;或者是追加切片
  • 使用append()函数为切片动态添加元素时,如果空间不足以容纳足够多的元素,切片就会进行“扩容”,此时新切片的长度会发生改变。
  • 扩展容量小于1024个元素时按当前切片的容量(Cap)2倍扩容,扩展容量大于1024个元素时按Cap的1/4扩容。
package main
import“fmt”
func main() {
    a := []int{10, 20, 30, 40, 50}
    b := a[1:3]
    fmt.Println(a)
    fmt.Println(b)
    b = append(b, 60)
    fmt.Printf(“第一次追加后,切片a为:%d 切片a容量为:%d\n", a, cap(a))
    fmt.Printf(“第一次追加后,切片b为:%d 切片b容量为:%d\n", b, cap(b))
    b = append(b, 70,80,90,100)
    fmt.Printf(“第二次追加后,切片a为:%d 切片a容量为:%d\n", a, cap(a))
    fmt.Printf(“第二次追加后,切片b为:%d 切片b容量为:%d\n", b, cap(b))
}



//运行结果为:
//[10 20 30 40 50]
//[20 30]
//第一次追加后,切片a为:[10 20 30 60 50] 切片a容量为:5
//第一次追加后,切片b为:[20 30 60] 切片b容量为:4
//第二次追加后,切片a为:[10 20 30 60 50] 切片a容量为:5
//第二次追加后,切片b为:[20 30 60 70 80 90 100] 切片b容量为:8

在对切片 b 进行第一次 append 时,由于它仍然指向 a 的底层数组,因此 a 和 b 共享数据;但第二次 append 超出容量时,切片 b 就会分配新的底层数组,不再共享 a 的数据。

使用copy()复制新的切片

copy(destSlice,srcSlice)

特点:

  • destSlice 为复制的目标切片
  • srcSlice 为数据来源切片
  • 目标切片必须分配过空间且足够承载复制的元素个数,并且来源和目标的类型必须一致。
  • copy() 函数来源切片和目标切片可以共享同一个底层数组,甚至有重叠也没有问题。
package main
import "fmt"
func main() {
    a := []int{0,1,2,3,4,5}
    b := []int{10,11,12}
    fmt.Println(a)
    fmt.Println(b)
    copy(b,a)  // 只会复制a的前3个元素到b中
    fmt.Println(a)
    fmt.Println(b)
}



//运行结果为:
//[0 1 2 3 4 5]
//[10 11 12]
//[0 1 2 3 4 5]
//[0 1 2]

数组与切片相互转换

  • 需要使用[:]将数组伪装为切片类型后再进行赋值,否则无法通过编译
  • 数组与切片中的元素类型必须相同

切片转成数组:

package main
import "fmt"
func main() {
    //切片转成数组
    s := []int{10, 11, 12}
    var a [3]int
    fmt.Println(copy(a[:], s))
    fmt.Println(a)
}


//运行结果为:
//3
//[10 11 12]

数组转成切片:

package main
import "fmt"
func main() {
    //数组转成切片
    a := [...]int{10, 11, 12}
    b := make([]int, 3)
    fmt.Println(copy(b, a[:]))
    fmt.Println(b)
}



//运行结果为:
//3
//[10 11 12]

三、Map映射

Map定义

一种无序的Key/value的集合
能够通过key值快速检索数据值
map这种数据结构在其他编程语言中也称为字典、映射或哈希表。
Golang的map由两种重要的结构构成:hmap和bmap

声明map集合:

var name map[key_type]value_type

语法说明如下:

  1. name为map变量名
  2. key_type为键类型
  3. value_type为键值对应值类型
package main
import "fmt"
func main() {
    a:=map[int]string{
        110:"报警电话",
        120:"急救电话",
        119:"消防电话"}
    fmt.Println(a)
}



//运行结果为:
//map[110:报警电话 119:消防电话 120:急救电话]

使用make()函数创建map

make(map[KeyType]ValueType, [cap])

特点:

  • map可以在声明的时候填充元素,也可以单独填充元素
  • map中的数据都是成对出现的
  • map类型的变量默认初始值为nil
  • 其中cap表示map的容量,该参数虽然不是必须的,但是我们应该在初始化map的时候就为其指定一个合适的容量。

用切片作为map的值


//示例1

package main
import "fmt"
func main() {
    a := make(map[string]int,10)
    a["报警电话"] = 110;
    a["急救电话"] = 120;
    a["火警电话"] = 119;
    fmt.Println(a)
}




//运行结果为:
//map[急救电话:120 报警电话:110 火警电话:119]


//示例2
package main
import "fmt"
func main() {
    //map的值为切片:
    a := make(map[int][]string, 2)// 创建一个容量为 2 的 map,键为 int,值为 []string(切片)
    a[1] = make([]string, 0, 2)      // 为键 1 初始化一个长度为 0、容量为 2 的切片
    a[1] = append(a[1], "A", "a") // 向切片中追加元素 "A" 和 "a"
    fmt.Println(a)
}


//运行结果为:
//map[1:[A a]]


//示例3
package main
import "fmt"
func main() {
   //切片的元素类型为map:
    b := make([]map[string]int, 2)
    b[0] = make(map[string]int, 2)
    b[0]["A"] = 1
    b[0]["a"] = 2
    fmt.Println(b)
}






//运行结果为:
//[map[A:1 a:2] map[]]

使用delete()函数删除元素

delete(map,key)

特点:

  • 如果要删除的key不存在,那么这个调用将什么都不发生,也不会有什么副作用
  • 但是如果传入的map变量的值是nil,该调用将导致程序抛出异常(panic)
示例
package main
import "fmt"
func main() {
    a:=map[int]string{
        110:"报警电话",
        120:"急救电话",
        119:"消防电话"}
    delete(a,110)
    fmt.Println(a)
}


//运行结果为:
//map[119:消防电话 120:急救电话]

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

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

相关文章

二叉树的各种操作补充

二叉树的各种操作补充 求二叉树的结点数求二叉树的叶结点数求二叉树的高度求二叉树的第k层结点数查找指定结点层序遍历判断二叉树是否是完全二叉树 我们任然沿用二叉树的基本信息: typedef char BTDataType; typedef struct BinaryTreeNode {BTDataType _data;struc…

Go语言的常用内置函数

文章目录 一、Strings包字符串处理包定义Strings包的基本用法Strconv包中常用函数 二、Time包三、Math包math包概述使用math包 四、随机数包(rand) 一、Strings包 字符串处理包定义 Strings包简介: 一般编程语言包含的字符串处理库功能区别…

Perfetto中如何使用SQL语句

在使用 Perfetto 分析 Android 性能时,可以通过 Perfetto 提供的内置 SQL 查询来提取和分析不同的性能数据。Perfetto 允许你在 UI 界面或命令行中运行 SQL 查询,提取出 Trace 数据中包含的各种性能信息,比如 CPU 使用率、线程状态、内存分配…

QML项目实战:自定义TextField

目录 一.添加模块 import QtQuick.Controls 1.2 import QtQuick.Controls.Styles 1.4 import QtGraphicalEffects 1.15 二.自定义TextField 1.属性设置 2.输入框设置 3.按钮开关 三.效果 1.readonly为false 2.readonly为true 四.代码 一.添加模块 import QtQuick.…

【进阶】Stable Diffusion 插件 Controlnet 安装使用教程(图像精准控制)

Stable Diffusion WebUI 的绘画插件 Controlnet 最近更新了 V1.1 版本,发布了 14 个优化模型,并新增了多个预处理器,让它的功能比之前更加好用了,最近几天又连续更新了 3 个新 Reference 预处理器,可以直接根据图像生产…

DAF-FM DA与NO反应后,生成的产物能够发出强烈的绿色荧光,254109-22-3

一、基本信息 产品名称:DAF-FM DA(一氧化氮NO荧光探针DAF-FM) 英文名称:DAF-FM DA,DAF-FM diacetate CAS号:254109-22-3 分子式:C25H18F2N2O7 供应商:陕西新研博美生物科技 分…

在 Mac 和 Windows 系统中快速部署 OceanBase

OceanBase 是一款分布式数据库,具备出色的性能和高扩展性,可以为企业用户构建稳定可靠、灵活扩展性能的数据库服务。本文以开发者们普遍熟悉的Windows 或 Mac 环境为例,介绍如何快速上手并体验OceanBase。 一、环境准备 1. 硬件准备 OceanB…

使用Ant Design的Layout布局不能撑满整个屏幕问题解决方法

代码示例: import React, { useState } from react import {LaptopOutlined,NotificationOutlined,UserOutlined, } from ant-design/icons import type { MenuProps } from antd import { Layout, Menu, theme } from antd import routes from ./routes/index imp…

【ubuntu18.04】使用U盘制作ubuntu18.04启动盘操作说明

打开show application 打开Startup Disk 选择镜像 双击选择ubuntu的iso镜像 镜像下载地址 Ubuntu 18.04.6 LTS (Bionic Beaver) 制作镜像 注意: 制作镜像会格式化U盘,记得备份资料 点击Make Startup Disk,弹出如下对话框 点击Yes 输入管理员密码&a…

22.04Ubuntu---ROS2创建python节点

创建工作空间 mkdir -p 02_ros_ws/src 然后cd到该目录 创建功能包 在这条命令里,tom就是你的功能包 ros2 pkg create tom --build-type ament_python --dependencies rclpy 可以看到tom功能包已经被创建成功了。 使用tree命令,得到如下文件结构 此时…

《手写Spring渐进式源码实践》实践笔记(第十七章 数据类型转换)

文章目录 第十七章 数据类型转换工厂设计实现背景技术背景Spring数据转换实现方式类型转换器(Converter)接口设计实现 业务背景 目标设计实现代码结构类图实现步骤 测试事先准备属性配置文件转换器工厂Bean测试用例测试结果: 总结 第十七章 数…

使用docker形式部署jumpserver

文章目录 前言一、背景二、使用步骤1.基础环境准备2.拉取镜像3.进行部署4.备份记录启动命令 前言 记录一下使用docker形式部署jumpserver服务的 一、背景 搭建一个jumpserver的堡垒机,但是发现之前是二进制文件部署的,会在物理机上部署污染环境&#x…

(62)使用RLS自适应滤波器进行系统辨识的MATLAB仿真

文章目录 前言一、基本概念二、RLS算法原理三、RLS算法的典型应用场景四、MATLAB仿真代码五、仿真结果1.滤波器的输入信号、参考信号、输出信号、误差信号2.对未知系统进行辨识得到的系数 总结与后续 前言 RLS(递归最小二乘)自适应滤波器是一种用于系统…

算法每日双题精讲——滑动窗口(长度最小的子数组,无重复字符的最长子串)

🌟快来参与讨论💬,点赞👍、收藏⭐、分享📤,共创活力社区。 🌟 别再犹豫了!快来订阅我们的算法每日双题精讲专栏,一起踏上算法学习的精彩之旅吧!💪…

MySQL数据库的备份与还原

目录 mysql 数据库的备份 生成SQL脚本 1 在控制台使用mysqldump命令可以用来生成指定数据库的脚本 ​编辑2 在数据库图形化界面工具:DateGrip 中操作:导出 mysql 数据库的还原 执行SQL脚本 1 在控制台使用 命令,指定将sql脚本导入到指定…

使用 IDEA 创建 Java 项目(二)

IDEA 创建 Java 项目 一般创建 Java 项目可以创建一个空项目,然后在空项目中添加模块,在模块中编写包,包中包含 Java 类。 如果你的 JDK 没有被 IDEA 自动找到的话,可以手动选择 JDK。我们先来学习 Intellij 构建系统下的 Java …

图论算法:最短路径算法详解【c语言版】(无权最短路径、Dijkstra算法)

别忘了请点个赞收藏关注支持一下博主喵!!! 图论算法:最短路径算法详解 在图论中,最短路径问题是寻找图中两点之间具有最小总权重的路径。这个问题在许多实际应用中都有重要的作用,比如网络路由、城市交通规…

vue通过iframe方式嵌套grafana图表

文章目录 前言一、iframe方式实现xxx.xxx.com拒绝连接登录不跳转Cookie 的SameSite问题解决不显示额外区域(kiosk1) 前言 我们的前端是vue实现的,监控图表是在grafana中的,需要在项目web页面直接显示grafana图表 一、iframe方式实现 xxx.xxx.com拒绝连…

苹果系统安装Homebrew时CLT缺失的问题

前言 为了使用brew命令,必须安装Homebrew工具。但是在Howebrew安装的时候,会出现CLT(Command Line Tools)缺失的问题。本博客就是讨论如何来解决这个问题的。 1、问题的出现 2、解决途径 在命令行终端中输入命令:xcod…

LeetCode Hot100 49.字母异位词分组

题干: 思路: 输入的是一个字符串数组,输出是一个列表,首先我们需要通过遍历数组获得每一个字符串,我们想要判断获得的任意两个字符串是不是字母异位词,所以可以将获得的字符串排序(转换为字符数…