Golang基础2-Array、Slice、Map

news/2024/9/20 1:29:19/ 标签: 算法

Array

数组

    1. var a [5]int b:=[5]int{} c:=[...]int{}这样格式定义
    2. var a[5]int 和var a[10]int是不同类型
    3. 从0开始下标,到len(a)-1
    4. 遍历方式:
for i := 0; i < len(a); i++ {
}for index, v := range a {
}
    1. 注意越界问题,panic
    2. 值类型,传参时会拷贝产生副本,不是指针 (因此会有性能问题)可以考虑传指针或者slice等引用类型
    3. 指针数组 [n]*T 数组指针 *[n]T。

简单demo

package mainimport "fmt"// 定义数组测试
func Test1() {var a [5]intb := [...]float64{1, 2, 3}//cap和len都会输出数组长度lenA := cap(a)lenB := len(b)fmt.Println(a, lenA)fmt.Println(b, lenB)//[0 0 0 0 0] 5//[1 2 3] 3
}// 循环输出测试
func PrintArr(arr [5]int) {//对比地址可以发现是拷贝的值fmt.Println(&arr[0])//循环输出元素测试for i := 0; i < len(arr); i++ {fmt.Println(i, "->", arr[i])}fmt.Println("***********************")for index, value := range arr {fmt.Println(index, "->", value)}
}func main() {//Test1()arr := [5]int{1, 2, 3, 4}fmt.Println(&arr[0])PrintArr(arr)
}

Slice

切片

最常用,最重要类型之一

变长序列,引用了数组对象,灵活

指针(底层数组,但不一定数组首地址),长度len,容量cap

初始化demo

package mainimport "fmt"func main() {//var arr1 [5]int//声明切片,注意与数组对比var s1 []intif s1 == nil {fmt.Println("初始化为空!")} else {fmt.Println("不为空!")}fmt.Println(s1)// :=s2 := []int{}fmt.Println(s2)// make方式 len(2) cap(3)var s3 []int = make([]int, 2, 3)fmt.Println(s3, "len(s3)=", len(s3), " cap(s3)=", cap(s3))//len(4) cap(4)s4 := make([]int, 4)fmt.Println(s4, "len(s4)=", len(s4), " cap(s4)=", cap(s4))//从数组中切片arr := [5]int{1, 2, 3, 4, 5}//左[  右)s6 := arr[1:4]fmt.Println(s6)
}

简单理解slice底层demo

具体源码在src/runtime/slice.go当中

package mainimport "fmt"func main() {arr := [6]int{0, 1, 2, 3, 4, 5}x := arr[:6]y := arr[1:3]fmt.Println(arr)fmt.Println(x, y)//    [0 1 2 3 4 5]//    [0 1 2 3 4 5] [1 2]fmt.Println()arr[1] = 100fmt.Println(arr)//实际操作底层数组fmt.Println(x, y)//    [0 100 2 3 4 5]//    [0 100 2 3 4 5] [100 2]fmt.Println()x[2] = 200fmt.Println(arr)//实际操作底层数组fmt.Println(x, y)
}

追加元素append demo

共享内存下容易出现的bug,请仔细分析

老数组

初始化时若:newSlice := array[1:2:2] ,如果第三个值(cap(slice))大于len(slice)

cap>len的时候请注意共享内存下的数据。

package mainimport "fmt"// 切片len<cap 注意会影响共享内存下的值
func main() {array := [4]int{10, 20, 30, 40}slice := array[0:2]newSlice := append(slice, 300)//这两个很有区别,这个扩容超出cap进行重新分配//newSlice := append(slice, 300, 400, 500)fmt.Println(slice, newSlice)fmt.Printf("&slice=%p &newSlice=%p\n", &slice, &newSlice)fmt.Printf("&slice[0]=%p &newSlice[0]=%p\n", &slice[0], &newSlice[0])fmt.Println(slice, newSlice, array)newSlice[1] = 200fmt.Printf("&slice=%p &newSlice=%p\n", &slice, &newSlice)fmt.Printf("&slice[0]=%p &newSlice[0]=%p\n", &slice[0], &newSlice[0])fmt.Println(slice, newSlice, array)
}

新数组:

扩容策略,即内存不够的时候重新分配array数组

当cap比较小的时候,扩容直接2倍

随着增大就扩容1/3,1/4等等逐渐减少

新数组扩容demo

package mainimport "fmt"// 了解分配策略
func main() {//初始化sliceslice := []int{0}c := cap(slice)num := 0 //计数,扩容次数for i := 0; i < 1024; i++ {//添加前cappreArr := &slice[0]preSlice := &sliceslice = append(slice, i)//添加后cap变大了就代表扩容了if n := cap(slice); n > c {fmt.Println("cap:", c, " --> ", n)fmt.Printf("  扩容前后底层array地址:%p --> %p\n", preArr, &slice[0])fmt.Printf("  扩容前后slice地址:%p --> %p\n\n", preSlice, &slice)c = nnum++}}fmt.Println("扩容了", num, "次!")}

总结:对于slice append造成扩容时,其slice的地址&slice不变,变化的是其内部array的地址

Slice详解分析:

https://halfrost.com/go_slice/

删除切片某元素demo

go语言并没有删除切片元素的接口,因此只能根据特性删除,[:]

删除开头元素:

    //方法1:移动array的指针   s := []int{1, 2, 3, 4}fmt.Printf("%#v\n", s)//fmt.Println(unsafe.Sizeof(int(0)))fmt.Printf("&s = %p\n", &s)fmt.Printf("&s[0] = %p\n\n", &s[0])//删除前两个元素,把底层的ptr向右移动s = s[2:]fmt.Printf("%#v\n", s)fmt.Printf("&s = %p\n", &s)fmt.Printf("&s[0] = %p\n\n", &s[0])//方法2:不改变array指针,但是代价是后面array数据向前移动s := []int{1, 2, 3, 4}fmt.Printf("&s = %p\n", &s)fmt.Printf("&s[0] = %p\n\n", &s[0])//删除掉a[0]s = append(s[:0], s[1:]...)fmt.Printf("%#v\n", s)fmt.Printf("&s = %p\n", &s)fmt.Printf("&s[0] = %p\n\n", &s[0])//方法3:copy函数辅助s := []int{1, 2, 3, 4}fmt.Printf("%#v\n", s)fmt.Printf("&s = %p\n", &s)fmt.Printf("&s[0] = %p\n\n", &s[0])//删除掉a[0] a[1]s = s[:copy(s, s[2:])]fmt.Printf("%#v\n", s)fmt.Printf("&s = %p\n", &s)fmt.Printf("&s[0] = %p\n\n", &s[0])

删除中间元素

    s := []int{0, 1, 2, 3, 4, 5, 6, 7}fmt.Printf("%#v\n", s)fmt.Printf("&s = %p\n", &s)fmt.Printf("&s[0] = %p\n\n", &s[0])//删除a[3]//s = append(s[:3], s[4:]...)//s = s[:3+copy(s[3:], s[4:])] // 删除中间1个元素//删除a[3]之后的3个元素//s = append(s[:3], s[6:]...)s = s[:3+copy(s[3:], s[6:])] // 删除中间1个元素fmt.Printf("%#v\n", s)fmt.Printf("&s = %p\n", &s)fmt.Printf("&s[0] = %p\n\n", &s[0])

删除尾部元素

a = []int{1, 2, 3}
a = a[:len(a)-1] // 删除尾部1个元素
a = a[:len(a)-N] // 删除尾部N个元素

切片删除元素:Go语言从切片中删除元素

container/list

这个是container中的list使用,也常见,了解即可。

package mainimport ("container/list""fmt"
)func main() {var mylist = list.List{}mylist.PushBack(123)mylist.PushBack(456)mylist.PushBack(789)fmt.Println(mylist)// 遍历listfor i := mylist.Front(); i != nil; i = i.Next() {fmt.Println(i.Value)}fmt.Println("--------------")for i := mylist.Back(); i != nil; i = i.Prev() {fmt.Println(i.Value)}// 其他需求,自己查阅资料}

https://juejin.cn/post/6888117219213967368#heading-2

Map

哈希表,无序key/value键值对

map[keyType][valueType] ,key是唯一的,其对应的value也唯一

map必须初始化才能读写,否则只能读

线程不安全,在多线程当中使用sync.Map,我编辑在了并发编程当中

简单demo

package mainimport "fmt"// 全局初始化
var map1 map[int]stringfunc main() {//等价//可以声明时初始化//scoreMap := map[string]int{}//可以声明初始化空间scoreMap := make(map[string]int, 0)scoreMap["张三"] = 100scoreMap["赵六"] = 10scoreMap["李四"]=60// 双参数返回,val,ok,如果单参数val,!ok返回空,有可能key是空if value, ok := scoreMap["张三"]; ok {fmt.Println(value)} else {fmt.Println("查无此人")}fmt.Println(scoreMap)fmt.Printf("%#v\n", scoreMap)// 删除key,valuedelete(scoreMap, "张三")fmt.Println(scoreMap)fmt.Printf("%#v\n", scoreMap)
}

输出是没有顺序的,如果想要按照一定顺序,可以先取出key,然后排序,之后输出。

key对应一个value,其中如果value切片的话会很灵活,map类型的切片也很灵活

对map进行打印

    var courseMap = map[string]string{"go":   "go语言圣经","gin":  "深入理解gin框架","grpc": "grpc理解",}for key, value := range courseMap {fmt.Println(key, "-->", value)}fmt.Println("---------------")for key := range courseMap {fmt.Println(key, "-->", courseMap[key])}

http://www.ppmy.cn/news/1433377.html

相关文章

【Node.js工程师养成计划】之打造自己的脚手架工具

一、创建全局的自定义命令 1、打开一个空文件夹&#xff0c;新建一个bin文件夹&#xff0c;在bin文件夹下新建cli.js文件&#xff0c;js文件可以命名为cli.js&#xff08;您随意&#xff09; 2、在cli.js文件中的开头&#xff08;&#xff01;&#xff01;&#xff09;写下面这…

UE5 C++ 使用TimeLine时间轴实现开关门

一.添加门头文件 和 声明 #include "Components/TimelineComponent.h" #include"Components/BoxComponent.h" UPROPERTY(EditAnywhere,BlueprintReadWrite,Category "MyCurve")UCurveFloat* MyCurveFloat;UPROPERTY(EditAnywhere, BlueprintR…

OpenHarmony语言基础类库【@ohos.buffer (Buffer)】

ohos.buffer (Buffer) Buffer对象用于表示固定长度的字节序列&#xff0c;是专门存放二进制数据的缓存区。 推荐使用场景&#xff1a; 可用于处理大量二进制数据&#xff0c;图片处理、文件接收上传等。 说明&#xff1a; 本模块首批接口从API version 9开始支持。后续版本的…

从零学算法134

134.加油站 在一条环路上有 n 个加油站&#xff0c;其中第 i 个加油站有汽油 gas[i] 升。 你有一辆油箱容量无限的的汽车&#xff0c;从第 i 个加油站开往第 i1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发&#xff0c;开始时油箱为空。 给定两个整数数组 gas …

redis单线程模型

工作原理 在Redis中&#xff0c;当两个客户端同时发送相同的请求时&#xff0c;Redis采用单线程模型来处理所有的客户端请求&#xff0c;会依次处理这些请求&#xff0c;每个请求都会按照先后顺序被执行&#xff0c;不会同时处理多个请求。使得Redis能够避免多线程并发访问数据…

S-Edge网关:柔性部署,让物联网接入更统一

S-Edge网关是什么&#xff1f; 网关是在实际物理世界与虚拟网络世界相连接的交叉点&#xff0c;为了让这个交叉点尽可能的复用&#xff0c;无需每种设备都配套一种连接方式&#xff0c;边缘网关主要就是用于传感器等物理设备与网络实现数据交互的通用设备&#xff0c;也称为物…

Python 环境管理工具:Conda

目录 一、Conda介绍 二、安装Conda 2.1 下载Anaconda 安装程序 2.2 执行安装 2.3 初始化Conda 2.4 配置镜像源 三、Conda常用命令 3.1 环境管理命令 3.2 包管理命令 3.3 配置相关命令 3.4 其他常用命令 一、Conda介绍 Conda 是一个开源的跨平台包…

ubuntu 23.04 Dell T3660 听歌没声音的尝试

首先&#xff0c;还是要安装PulseAudio Volume Control sudo apt install pulseaudio 或者 snap install pulseaudio 装了pulseaudio可以在configure和playback间切换选择用哪个声卡输出声音&#xff0c;一般选Stereo Analog Output 网上其他办法也可以试试&#xff0c;比…

HashTable ,HashMap,和ConcurrentHashMap的区别

这里呢&#xff0c;在我们学习多线程之前&#xff0c;HashMap,在数据结构中我们都已经非常熟悉了&#xff0c;HashMap&#xff0c;有key和value&#xff0c;key和value都是一一对应的关系。key允许为null。 而当我们学习过线程之后呢&#xff0c;HashMap是线程不安全的。 而Has…

【LeetCode热题100】【多维动态规划】最小路径和

题目链接&#xff1a;64. 最小路径和 - 力扣&#xff08;LeetCode&#xff09; 给定一个包含非负整数的 m x n 网格 grid &#xff0c;请找出一条从左上角到右下角的路径&#xff0c;使得路径上的数字总和为最小。 说明&#xff1a;每次只能向下或者向右移动一步。 经典动态规…

【iOS】类与对象底层探索

文章目录 前言一、编译源码二、探索对象本质三、objc_setProperty 源码探索四、类 & 类结构分析isa指针是什么类的分析元类元类的说明 五、著名的isa走位 & 继承关系图六、objc_class & objc_objectobjc_class结构superClassbitsclass_rw_tclass_ro_tro与rw的区别c…

银河麒麟V10 SP1服务器客户端定时数据同步

银河麒麟V10 SP1服务器客户端定时数据同步 0.概述 当前只测试了将数据从客户端往服务端推送&#xff0c;两个客户端分别推送不同的数据 1.环境 三台电脑均为银河麒麟V10SP1桌面操作系统 服务器IP&#xff1a;192.168.1.51 用户名&#xff1a;wlh 客户端IP&#xff1a;192…

什么是架构?说说我的理解

什么是架构了&#xff1f;其实就是根据企业的具体情况给出的一个解决方案&#xff0c;并且这个架构能升级&#xff0c;如果企业的流量突然暴增&#xff0c;也能适应变化&#xff0c;这才是好的架构&#xff0c;一个项目是采用单体架构了&#xff1f;还是采用前后端分离&#xf…

elment ui 中el-input标签中@input初始化赋值触发问题

遇见问题记录起来&#xff0c;方便以后隔了很久再次遇到。 elment ui 中el-input标签中input初始化赋值时会触发到input方法 <el-input-numberv-model"scope.row.discount_value":controls"false":min"0":precision"0"input"…

练习题(2024/4/23)

1分发糖果 n 个孩子站成一排。给你一个整数数组 ratings 表示每个孩子的评分。 你需要按照以下要求&#xff0c;给这些孩子分发糖果&#xff1a; 每个孩子至少分配到 1 个糖果。相邻两个孩子评分更高的孩子会获得更多的糖果。 请你给每个孩子分发糖果&#xff0c;计算并返回…

解密数字化工业革命:数字孪生工厂和信息集成

数字孪生工厂与信息集成&#xff01; 虚拟工厂是将实体工厂映射过来&#xff0c;具备仿真、管理和控制实体工厂关键要素功能的模型化平台。数字孪生技术将虚拟工厂的概念不断深入&#xff0c;利用物联网技术和监控技术加强信息管理服务&#xff0c;通过合理计划排程&#xff0c…

设计模式(四):单例模式

设计模式&#xff08;四&#xff09;&#xff1a;单例模式 1. 单例模式的介绍2. 单例模式的类图3. 单例模式的实现3.1 懒汉式&#xff08;线程不安全&#xff09;3.2 懒汉式&#xff08;线程安全&#xff09;3.3 饿汉式3.4 静态内部类3.5 枚举 1. 单例模式的介绍 单例模式&…

git常见命令(成长版)

ps&#xff1a;所谓成长版就是后续可能还会添加命令&#xff1a; 1.删除本地分支&#xff1a; git branch -d 分支名 2.拉取代码后默认master分支&#xff0c;切换到线上其他分支&#xff1a; &#xff08;1&#xff09;查看线上所有分支&#xff1a; git branch -a &#…

ES6 - 语法糖

ES6 引入了许多新的语法糖和方法&#xff0c;其中一些包括&#xff1a; 箭头函数&#xff1a;() > {} 模板字符串&#xff1a;${variable} 解构赋值&#xff1a;const { prop } object 类和继承&#xff1a;class MyClass extends ParentClass {} Promise&#xff1a;…

【华为OD机试】精准核酸检测【C卷|100分】

【华为OD机试】-真题 !!点这里!! 【华为OD机试】真题考点分类 !!点这里 !! 题目描述 为了达到新冠疫情精准防控的需要,为了避免全员核酸检测带来的浪费,需要精准圈定可能被感染的人群。现在根据传染病流调以及大数据分析,得到了每个人之间在时间、空间上是否存在轨迹交叉…