【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 多章⑧ (叁) 指针与字符串、(肆) 函数与指针…...
Linux应用开发之网络套接字编程(实例篇)
服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...
进程地址空间(比特课总结)
一、进程地址空间 1. 环境变量 1 )⽤户级环境变量与系统级环境变量 全局属性:环境变量具有全局属性,会被⼦进程继承。例如当bash启动⼦进程时,环 境变量会⾃动传递给⼦进程。 本地变量限制:本地变量只在当前进程(ba…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...
Module Federation 和 Native Federation 的比较
前言 Module Federation 是 Webpack 5 引入的微前端架构方案,允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...
Map相关知识
数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...
CMake控制VS2022项目文件分组
我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...
python执行测试用例,allure报乱码且未成功生成报告
allure执行测试用例时显示乱码:‘allure’ �����ڲ����ⲿ���Ҳ���ǿ�&am…...
网站指纹识别
网站指纹识别 网站的最基本组成:服务器(操作系统)、中间件(web容器)、脚本语言、数据厍 为什么要了解这些?举个例子:发现了一个文件读取漏洞,我们需要读/etc/passwd,如…...
GruntJS-前端自动化任务运行器从入门到实战
Grunt 完全指南:从入门到实战 一、Grunt 是什么? Grunt是一个基于 Node.js 的前端自动化任务运行器,主要用于自动化执行项目开发中重复性高的任务,例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...
