【Go语言学习笔记】数据
目录
- 字符串
- 数组
- 数组初始化
- 指针
- 复制
- 切片
- 基本操作
- reslice
- append
- copy
- 字典
- delete
- map是引用类型
- 并发操作
字符串
字符串是不可变字节(byte)序列,其本身是一个复合结构
type stringStruct struct{str unsafe.Pointerlen int
}
头部指针指向字节数组,但没有null结尾,默认以utf-8编码粗出Unicode字符,字面量李允许使用十六进制、八进制和UTF编码格式。默认值是""而不是null。
使用"`"定义不做转移处理的原始字符串,支持跨行
func main() {s := `line\r\n,line 2`println(s)
}
- 支持
!=、==、<、>、+、+=
操作符 - 允许以索引号访问字节数组,但不能获取元素地址
- 以切片语法返回子串时,其内部依旧指向原字节数组
- 使用for遍历字符串时,分byte和rune两种方式;
func main() {s := "哈喽"for i := 0; i < len(s); i++ { // bytefmt.Printf("%d: [%c]\n", i, s[i])}for i, c := range s { // rune 返回数组索引号 以及unicode字符fmt.Printf("%d: [%c]\n", i, c)}0: [å]1: [ ]2: [ ]3: [å]4: [ ]5: [½]0: [哈]3: [喽]}
数组
定义数组类型时,数组长度必须是非负整形常量表达式,长度是类型组成部分,所以,元素类型相同但是长度不同的数组不属于同一类型
func main() {d1 := [3]int{}d2 := [2]int{}d1 = d2 // cannot use d2 (variable of type [2]int) as type [3]int in assignment
}
数组初始化
var a [4]int // 元素自动初始化为0 [0 0 0 0]b := [4]int{2, 5} // 未提供初始值得元素自动初始化为0 [2 5 0 0]c := [4]int{5, 3: 100} // 可指定索引位置初始化 [5 0 0 100]d := [...]int{1, 2, 3} // 编译器按初始化值数量确定数组长度 [1 2 3]e := [...]int{10, 3: 100} // 支持索引初始化,但是数组长度与此有关 [10 0 0 100]fmt.Println(a, b, c, d, e)
对于结构等复合类型,可省略元素初始化类型标签
type user struct {name stringage byte}d := [...]user{{"Tome", 20}, // 省略了类型标签{"Mary", 18}}fmt.Printf("%#v\n", d)
在定义多维数组时,仅第一维度允许使用“…”
a := [2][2]int{{1, 2},{3, 4},}b := [...][2]int{{10, 20},{30, 40},}c := [...][2][2]int{{{1, 2},{3, 4},},{{10, 20},{30, 40},},}fmt.Println(a)fmt.Println(b)fmt.Println(c)[[1 2] [3 4]][[10 20] [30 40]][[[1 2] [3 4]] [[10 20] [30 40]]]
内置函数len和cap都返回第一维度长度;
如果元素类型支持==、!=
操作符,那么数组也支持此操作
指针
要分清楚指针数组和数组指针的区别,指针数组是指元素为指针类型的数组,数组指针是获取数组变量的地址。
x, y := 10, 20a := [...]*int{&x, &y} // 指针数组p := &a // 数组指针fmt.Printf("%T,%v\n", a, a) //[2]*int,[0xc000018088 0xc0000180a0]fmt.Printf("%T,%v\n", p, p) //*[2]*int,&[0xc000018088 0xc0000180a0]// 获取任意元素地址println(&a, &a[0], &a[1])//数组指针可以直接用来操作元素c := [...]int{1, 2}d := &cd[1] += 10println(d[1])
复制
Go数组是值类型,赋值和传参操作都会复制整个数组数据。
func test(a [3]int) {println(&a, &a[0], &a[1], &a[2]) // 传参 0xc0000cbf40 0xc0000cbf40 0xc0000cbf48 0xc0000cbf50
}func main() {a := [...]int{1, 2, 3}println(&a, &a[0], &a[1], &a[2]) // 0xc0000cbf58 0xc0000cbf58 0xc0000cbf60 0xc0000cbf68b := aprintln(&b, &b[0], &b[1], &b[2]) //赋值 0xc0000cbf28 0xc0000cbf28 0xc0000cbf30 0xc0000cbf38test(a)
如果需要,可改用指针或者切片,以避免数据复制
func test(a *[3]int) {println(&a, &a[0], &a[1], &a[2]) // 指针传参 0xc00007bf50 0xc00007bf38 0xc00007bf40 0xc00007bf48
}func main() {a := [...]int{1, 2, 3}println(&a, &a[0], &a[1], &a[2]) // 0xc00007bf38 0xc00007bf38 0xc00007bf40 0xc00007bf48b := a[:]println(&b, &b[0], &b[1], &b[2]) //切片赋值 0xc00007bf58 0xc00007bf38 0xc00007bf40 0xc00007bf48var c = &a // 指针赋值 0xc00007bf68 0xc00007bf38 0xc00007bf40 0xc00007bf48println(&c, &c[0], &c[1], &c[2])test(&a)
切片
基本操作
切片本身并非动态数组或数组指针,内部通过指针引用底层数组,设定相关属性将数据读写操作限定在指定区域内。其本身是个只读对象,工作机制类似数组指针的一种包装。
x := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}x1 := x[:]x2 := x[2:5]x3 := x[2:5:7]x4 := x[4:]x5 := x[:4]x6 := x[:4:6]fmt.Println(x1, len(x1), cap(x1)) // [0 1 2 3 4 5 6 7 8 9] 10 10fmt.Println(x2, len(x2), cap(x2)) // [2 3 4] 3 8fmt.Println(x3, len(x3), cap(x3)) // [2 3 4] 3 5fmt.Println(x4, len(x4), cap(x4)) // [4 5 6 7 8 9] 6 6fmt.Println(x5, len(x5), cap(x5)) // [0 1 2 3] 4 10fmt.Println(x6, len(x6), cap(x6)) // [0 1 2 3] 4 6
属性cap表示切片所引用数组片段的真实长度,len用于限定可读的写元素数量。
cap表示切片引用数组的容量,该数组可以插入多少个元素,如果cap不够则需要扩容
x3 = append(x3, 1000)x3 = append(x3, 1001)fmt.Println(x3, len(x3), cap(x3)) // [2 3 4 1000 1001] 5 5println(&x3)x3 = append(x3, 1002)fmt.Println(x3, len(x3), cap(x3)) //cap不够,发生扩容,cap变成10 [2 3 4 1000 1001 1002] 6 10println(&x3)
可以直接创建切片对象,无须预先准备数组,因为是引用类型,须使用make函数或显
s1 := make([]int, 3, 5) // 指定len、cap底层数组初始化为零值s2 := make([]int, 3) // 省略cap 和len 相等s3 := []int{10, 20, 5: 30} // 按初始化元素分配底层数组,并设置 len、capfmt.Println(s1, len(s1), cap(s1)) // [0 0 0] 3 5fmt.Println(s2, len(s2), cap(s2)) // [0 0 0] 3 3fmt.Println(s3, len(s3), cap(s3)) // [10 20 0 0 0 30] 6 6
可以获取元素地址,但是不能向数组那样直接用指针访问元素内容
s := []int{0, 1, 2, 3, 4}p := &sp0 := &s[0]p1 := &s[1]println(p, p0, p1) // 0xc00007bf58 0xc00000a360 0xc00000a368(*p)[0] += 100 // *[]int 不支持索引操作 须先返回[]int对象 mismatched types []int and untyped int*p1 += 100fmt.Println(s) // [100 101 2 3 4]
reslice
对切片再次进行切片,不能超出cap,但是不受len限制。新切片对象依旧指向原底层数组,也就是说修改对所有关联切片可见。
d := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}s1 := d[3:7]s2 := s1[:3]s2[1] = 100println(&s1[0]) // 0xc000014298println(&s2[0]) // 0xc000014298fmt.Println(s1) // [3 4 100 6]fmt.Println(s2) // [3 100 5]
append
向切片尾部添加数据,返回新的切片对象
s := make([]int, 0, 5)s1 := append(s, 10)s2 := append(s1, 20, 30)fmt.Println(s, len(s), cap(s)) // [] 0 5fmt.Println(s1, len(s1), cap(s1)) // [10] 1 5fmt.Println(s2, len(s2), cap(s2)) // [10 20 30] 3 5
数据被追加到原底层数组,如超出cap限制,则为新切片对象重新分配数组。
copy
在两个切片对象间复制数据,允许指向同一底层数组,允许目标区间重叠,最终所复制长度以较短的切片长度为准。
d := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}s1 := d[5:8]n := copy(d[4:], s1) // 在同一底层数组的不同区间复制fmt.Println(n, d) // 3 [0 1 2 3 5 6 7 7 8 9]s2 := make([]int, 6)n = copy(s2, d) // 在不同数组间复制fmt.Println(n, s2) // 6 [0 1 2 3 5 6]
字典
字典是引用类型,使用make函数或初始化表达语句来创建。
m := map[string]int{"a": 1,"b": 2,}fmt.Println(m)m["a"] = 10 // 修改m["c"] = 30 // 新增if v, ok := m["d"]; ok { // 使用ok-idiom 判断key是否存在println(v)}delete(m, "d") // 删除键值对,不存在时,不会出错
访问不存在的键值对,默认返回零值,不会引发错误,但推荐使用ok-idiom模式,毕竟通过零值无法判断键值是否存在,或许存储的value本身就是零。
因内存访问安全和河西算法等缘故,字典被设计成“not addressable” 故不能直接修改value成员。
正确做法时返回整个value,待修改后再设置字典键值,或直接用指针类型。
type user struct {name stringage byte}m := map[int]user{1: {"Tome", 19},}//m[1].age += 1 // Cannot assign to m[1].ageu := m[1]u.age += 1m[1] = ufmt.Println(m) // map[1:{Tome 20}]m2 := map[int]*user{1: &user{"Jack", 20},}m2[1].age++
delete
在迭代期间删除或新增键值时安全的。
m := make(map[int]int)for i := 0; i < 10; i++ {m[i] = i + 10}for k := range m {if k == 5 {m[100] = 1000}delete(m, k)fmt.Println(k, m)}//1 map[0:10 2:12 3:13 4:14 5:15 9:19]//3 map[0:10 2:12 4:14 5:15 9:19]//4 map[0:10 2:12 5:15 9:19]//5 map[0:10 2:12 9:19 100:1000]//0 map[2:12 9:19 100:1000]//2 map[9:19 100:1000]//9 map[100:1000]
不能保证迭代操作会删除新增的键值
Go没有为map提供清空所有元素的函数,清空map唯一的办法是重新make一个新的map。
Go语言的垃圾回收比写一个清空函数更高效
map是引用类型
map与切片相似,都是引用类型。将一个map赋值给一个新的变量时,它们指向同一块内存,因此修改两个变量的内容都能够引起它们所指向的数据发生变化。
map1 := map[string]string{"hello":"123","demo":"321",}fmt.Println("原始map: ",map1)newMap := map1newMap["hello"]="456"fmt.Println("修改后newMap: ",newMap)fmt.Println("修改后map: ",map1)
// 原始map: map[demo:321 hello:123]
// 修改后newMap: map[demo:321 hello:456]
// 修改后map: map[demo:321 hello:456]
并发操作
运行时会对字典并发操作做出检测,如果某个任务正在对字段进行写操作,那么其他任务就不能对该字典并发操作,否则会导致进程崩溃。
m := make(map[string]int)go func() {for {m["a"] += 1 // 写操作time.Sleep(time.Millisecond)}}()go func() {for {_ = m["b"] // 读操作time.Sleep(time.Millisecond)}}()select {} // 阻止进程退出// fatal error: concurrent map read and map write
相关文章:
【Go语言学习笔记】数据
目录字符串数组数组初始化指针复制切片基本操作resliceappendcopy字典deletemap是引用类型并发操作字符串 字符串是不可变字节(byte)序列,其本身是一个复合结构 type stringStruct struct{str unsafe.Pointerlen int }头部指针指向字节数组…...

puzzle(0919)六宫数局
目录 六宫数局 示例题目 简单模式 普通模式 困难模式 六宫数局 最强大脑同款项目。 找出一条给定起点和终点的路径,每一步的方向任选,在这个方向上移动的步数是当前数的质因数分解中2、3、5的次数。 示例题目 按照六边形坐标系来建立坐标系&#…...

脑机接口科普0016——独立BCI与非独立BCI
本文禁止转载!!!! 所谓的“独立BCI”与“非独立BCI”仅仅是BCI系统中的一个术语。本章主要是介绍一下这两个术语。 这两个术语是由Wolpaw在2002年提出来的。 独立BCI是指不依赖于中枢神经系统的的输出。 非独立BCI是指那种依赖…...

女神节告白代码
今天是女神节,送给所有女神们一句话: 爱自己是终生浪漫的开始,无论何时都要好好爱自己 目录 1. 请求动画帧填充 2.点类 3.粒子类 编辑 4.ParticlePool 池类 5.创建和填充 6.处理循环队列 7.更新活动粒子 8.移除非活性粒子 9.绘制有…...

【数据结构】单链表:头部操作我很行,插入也不用增容!!!
单链表 文章目录单链表1.链表1.1链表的概念和结构1.2链表的分类2.单链表的模拟实现2.1单链表的打印2.2单链表的尾插2.3单链表的头插2.4单链表的尾删2.5单链表的头删2.6单链表的查找2.7单链表的中间插入(在结点前插入)2.8单链表的中间删除(删除该结点)2.9单链表的中间插入(在结点…...

SpringBoot——使用WebSocket功能
springboot自带websocket,通过几个简单的注解就可以实现websocket的功能; 启动类跟普通的springboot一样: /*** 2023年3月2日下午4:16:57*/ package testspringboot.test7websocket;import org.springframework.boot.SpringApplication; im…...
博弈论小课堂:非零和博弈(实现双赢)【纳什均衡点】
文章目录 引言I 非零和博弈1.1 囚徒问题1.2 博弈中双方的收益矩阵II 在现实中找均衡点2.1 博弈通常不是一次性的,而是反复进行的2.2 博弈论讲的都是阳谋的策略2.3 人类还处于文明的初级阶段,人的道德水准不容高估2.4 乌合之众效应2.5 很多时候看似是双赢,其实是在更大范围内…...

数组中的逆序对
解题思路1: 看到这个题目,我们的第一反应是顺序扫描整个数组。每扫描到一个数组的时候,逐个比较该数字和它后面的数字的大小。如果后面的数字比它小,则这两个数字就组成了一个逆序对。假设数组中含有n个数字。由于每个数字都要和…...

C++基础了解-01-基础语法
基础语法 一、基础语法 C 程序可以定义为对象的集合,这些对象通过调用彼此的方法进行交互。现在让我们简要地看一下什么是类、对象,方法、即时变量。 对象 - 对象具有状态和行为。例如:一只狗的状态 - 颜色、名称、品种,行为 -…...
phpmyadmin 文件包含(CVE-2014-8959)
0x01 漏洞介绍 phpMyAdmin是phpMyAdmin团队开发的一套免费的、基于Web的MySQL数据库管理工具。该工具能够创建和删除数据库,创建、删除、修改数据库表,执行SQL脚本命令等。phpMyAdmin的GIS编辑器中libraries/gis/GIS_Factory.class.php脚本存在目录遍历漏洞。远程攻击者可借助…...
SpringBoot集成MyBatis
目录 实现步骤 1. 在项目的 pom.xml 配置文件中引入如下依赖 2. 在项目的 application.properties 配置文件中添加如下依赖 3. 新建 UserMapper.class 接口类,添加如下 3 个方法 4. 在 /resources/mybatis/mapper 路径(需要手动创建文件夹)下创建 UserMapper.xm…...
MySQL-索引
索引介绍索引是对数据库表中一列或者多列的值进行排序的一种结构,使用索引可提高数据库中特定数据的查询速度。索引是一个单独的、存储在磁盘上的数据库结构,它们包含着对数据表里所有记录的引用指针。使用索引用于快速找出在某个或多个列中有一特定值得…...

【STM32存储器映射-寄存器基地址-偏移】
前言 在学习STM32的时候,我们看到很多的寄存器编程, 比方说LED灯: //GPIOB.5端口输出高电平GPIOB->ODR|1<<5; //PB.5 输出高GPIOE->ODR|1<<5; //PE.5输出高 //GPIOB端口全部输出高电平*(unsigned int*)(0x4001 …...
【华为OD机试2023】最多颜色的车辆 C++ Java Python
【华为OD机试2023】最多颜色的车辆 C++ Java Python 前言 如果您在准备华为的面试,期间有想了解的可以私信我,我会尽可能帮您解答,也可以给您一些建议! 本文解法非最优解(即非性能最优),不能保证通过率。 Tips1:机试为ACM 模式 你的代码需要处理输入输出,input/cin接收…...
特斯拉后端面试(部分)
HR告知如果面试通过要转.net-_- round1 有没有用过Java新版本,知道有哪些特性吗?A:没有。Q:我们基本在用JDK11,有的新项目用到JDK17了。参考答案1: ZGC: A Scalable Low-Latency Garbage Collector Epsi…...

【python】使用python将360个文件夹里的照片,全部复制到指定的文件夹中,并且按照顺序重新命名
最近要做一个图像生成的课题,在网上找了一个混合的数据集。这个数据集中一共有360个文件夹,然后文件夹中有6-9张不等的照片,我的目标就是编写python代码将所有的照片取出来,放到一个指定的文件夹里,并且从1开始按照顺序…...

【C语言】3天速刷C语言(初识)
【声明】本篇博客只用于对与刚学习C语言的同学的一个初始了解,具体内容请继续关注本专栏后续内容。什么是C语言C语言是一门通用计算机编程语言,广泛应用于底层开发。C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及…...

如何搞定MySQL锁(全局锁、表级锁、行级锁)?这篇文章告诉你答案!太TMD详细了!!!
概述 锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中,除传统的计算资源(CPU、RAM、I/O)的争用以外,数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题&…...

云计算生态该怎么做?阿里云计算巢打了个样
2023 年 2 月 23 日至 24 日,由阿里云主办的「阿里云计算巢加速器」于杭州阿里云谷园区集结。 阿里云计算巢加速器于 2022 年 8 月正式启动招募,最终百奥利盟、极智嘉、EMQ、KodeRover、MemVerge 等 30 家创新企业入选计算加速器,覆盖了人工智…...

小樽C++ 多章⑧ (贰) 指针与数组
目录 1.C中数组变量名某些情况可以看成是指针 2.C语言的scanf 输入语句,printf 输出语句 3.用指针来当动态数组 小樽C 多章⑧ (壹) 指针变量https://blog.csdn.net/weixin_44775255/article/details/129031168 小樽C 多章⑧ (叁) 指针与字符串、(肆) 函数与指针…...

Spark 之 入门讲解详细版(1)
1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...
ssc377d修改flash分区大小
1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...
线程与协程
1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指:像函数调用/返回一样轻量地完成任务切换。 举例说明: 当你在程序中写一个函数调用: funcA() 然后 funcA 执行完后返回&…...

汽车生产虚拟实训中的技能提升与生产优化
在制造业蓬勃发展的大背景下,虚拟教学实训宛如一颗璀璨的新星,正发挥着不可或缺且日益凸显的关键作用,源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例,汽车生产线上各类…...

蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练
前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1):从基础到实战的深度解析-CSDN博客,但实际面试中,企业更关注候选人对复杂场景的应对能力(如多设备并发扫描、低功耗与高发现率的平衡)和前沿技术的…...
Python如何给视频添加音频和字幕
在Python中,给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加,包括必要的代码示例和详细解释。 环境准备 在开始之前,需要安装以下Python库:…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)
在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...
什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南
文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果
面向无人机海岸带生态系统监测的语义分割基准数据集
描述:海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而,目前该领域仍面临一个挑战,即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...