【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 多章⑧ (叁) 指针与字符串、(肆) 函数与指针…...

超短脉冲激光自聚焦效应
前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应,这是一种非线性光学现象,主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场,对材料产生非线性响应,可能…...

大话软工笔记—需求分析概述
需求分析,就是要对需求调研收集到的资料信息逐个地进行拆分、研究,从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要,后续设计的依据主要来自于需求分析的成果,包括: 项目的目的…...

【JVM】- 内存结构
引言 JVM:Java Virtual Machine 定义:Java虚拟机,Java二进制字节码的运行环境好处: 一次编写,到处运行自动内存管理,垃圾回收的功能数组下标越界检查(会抛异常,不会覆盖到其他代码…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...

苍穹外卖--缓存菜品
1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: ①每个分类下的菜品保持一份缓存数据…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...

NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...
MySQL用户和授权
开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务: test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...

C# 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...

关键领域软件测试的突围之路:如何破解安全与效率的平衡难题
在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件,这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下,实现高效测试与快速迭代?这一命题正考验着…...