golang复杂数据结构
作者:@daemon365
本文为作者原创,转载请注明出处:https://www.cnblogs.com/daemon365/p/15161246.html
数组
数组是一个由固定长度的特定类型元素组成的序列,一个数组可以由零个或多个元素组成。因为数组的长度是固定的,因此在Go语言中很少直接使用数组。
数组的每个元素可以通过索引下标来访问,索引下标的范围是从0开始到数组长度减1的位置。内置的len函数将返回数组中元素的个数。
var a [3]int // 长度为3的数组 fmt.Println(a[0]) // 打印第一个数据 fmt.Println(a[len(a)-1]) // 打印最后一个数据 for i, v := range a { fmt.Printf("%d %d\n", i, v) // 循环数组 i为索引 v为数据 }
默认情况下,数组的每个元素都被初始化为元素类型对应的零值
数组的初始化:
var a [3]int = [3]int{1, 2, 3} b := [...]int{1, 2, 3} a = [4]int{1, 2, 3, 4} // panic 数据初始化就是定长了 长度不能变化
切片
Slice(切片)代表变长的序列,序列中每个元素都有相同的类型。一个slice类型一般写作[]T,其中T代表slice中元素的类型;slice的语法和数组很像,只是没有固定长度而已。
一个slice由三个部分构成:指针、长度和容量。指针指向第一个slice元素对应的底层数组元素的地址,要注意的是slice的第一个元素并不一定就是数组的第一个元素。长度对应slice中元素的数目;长度不能超过容量,容量一般是从slice的开始位置到底层数据的结尾位置。内置的len和cap函数分别返回slice的长度和容量。
多个slice之间可以共享底层的数据,并且引用的数组部分区间可能重叠。
使用make()函数构造切片
make([]T, size, cap) // T:切片类型 size 切片数量 cap 切片容量
append()方法为切片添加元素
sli := make([]int,0,10) sli = append(sli,1) // 添加一个 1 arr := [4]int{6,7,8,9} sli = append(sle,arr...) // 把arr打散并全部添加 添加多个 fmt.Println(sli) // [1 6 7 8 9]
从切片中删除元素
// 从切片中删除元素 a := []int{30, 31, 32, 33, 34, 35, 36, 37} // 要删除索引为2的元素 a = append(a[:2], a[3:]...) fmt.Println(a) //[30 31 33 34 35 36 37]
切片的扩容策略
func growslice(et *_type, old slice, cap int) slice { newcap := old.cap doublecap := newcap + newcap if cap > doublecap { newcap = cap } else { if old.len < 1024 { newcap = doublecap } else { for 0 < newcap && newcap < cap { newcap += newcap / 4 } if newcap <= 0 { newcap = cap } } }
在分配内存空间之前需要先确定新的切片容量,Go 语言根据切片的当前容量选择不同的策略进行扩容:
- 如果期望容量大于当前容量的两倍就会使用期望容量;
- 如果当前切片容量小于 1024 就会将容量翻倍;
- 如果当前切片容量大于 1024 就会每次增加 25% 的容量,直到新容量大于期望容量;
MAP
哈希表是一种巧妙并且实用的数据结构。它是一个无序的key/value对的集合,其中所有的key都是不同的,然后通过给定的key可以在常数时间复杂度内检索、更新或删除对应的value。在Go语言中,一个map就是一个哈希表的引用,map类型可以写为map[K]V,其中K和V分别对应key和value。
- 初始化:
m := make(map[string]int)
- 赋值初始化
m := map[string]int{ "zhy": 18, "who": 30, } // 直接赋值相当于 ages := make(map[string]int) ages["zhy"] = 18 ages["who"] = 30
Map的迭代顺序是不确定的,并且不同的哈希函数实现可能导致不同的遍历顺序。遍历的顺序是随机的,每一次遍历的顺序都不相同。
如果要有序:
// 用sort进项排序 var names []string for name := range ages { names = append(names, name) } sort.Strings(names) for _, name := range names { fmt.Printf("%s\t%d\n", name, ages[name]) }
结构体
结构体是一种聚合的数据类型,是由零个或多个任意类型的值聚合成的实体。每个值称为结构体的成员。
type people struct { name string age uint8 hobby []string address string sex uint8 } var zhy people
结构体赋值
h := []string{"唱","跳","RAP","篮球"} zhy := people{"zhaohaiyu",18,h,"地球",1}
或者
var zhy people zhy.name = "zhaohaiyu" zhy.age = 18 zhy.hobby = h zhy.address = "地球" zhy.sex = 1
结构体比较
如果结构体的全部成员都是可以比较的,那么结构体也是可以比较的,那样的话两个结构体将可以使用或!=运算符进行比较。相等比较运算符将比较两个结构体的每个成员,因此下面两个比较的表达式是等价的:
type Point struct{ X, Y int } p := Point{1, 2} q := Point{2, 1} fmt.Println(p.X == q.X && p.Y == q.Y) // "false" fmt.Println(p == q) // "false"
结构体的继承
在java,python,cpp等语言中都有类的继承的概念,go语言中没有类.用结构体的嵌套实现继承.
type animal struct { name string age int } type people struct { address string animal animal } var zhy = people{ address: "地球", animal: animal{ name: "zhaohaiyu", age: 18, }, } fmt.Println(zhy.animal) // {zhaohaiyu 18} fmt.Println(zhy.animal.name) // zhaohaiyu fmt.Println(zhy.animal.age) // 18 fmt.Println(zhy.address) //地球
JSON
JSON(JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式。它基于ECMAScript(欧洲计算机协会制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
Go语言对于这些标准格式的编码和解码都有良好的支持,由标准库中的encoding/json包提供支持
JSON是对JavaScript中各种类型的值——字符串、数字、布尔值和对象——Unicode本文编码。它可以用有效可读的方式表示第三章的基础数据类型和本章的数组、slice、结构体和map等聚合数据类型。
- 各类型的json数据
boolean true number -273.15 string "hello world!!!!" array ["i", "you", "her"] object {"year": 2020, "event":"huawei","American virus","Trump is crazy"}
- go语言结构体成员Tag来指定对应的JSON名字。同样,在解码的时候也需要做同样的处理
type People struct { Name string `json:"name"` Age int `json:"age"` PhoneNumber string `json:"phone_number"` }
- 要将结构体的数据发给游览器前端或者安卓,IOS,APP等进行展示,因为go语言首字母小写只能本包用,在外部包要首字母大写,包括结构体和结构体成员.而且go语言崇尚驼峰体命名,而很多语言崇尚下划线命名.所有我们要用tag把json数据的成员变成首字母小写以及下划线命名.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?