Go语言常见数据结构实现原理

结构体

定义与初始化

结构体是一种可以包含不同类型的字段的数据类型。
示例代码:

type Person struct {Name stringAge  int
}func main() {var p Personfmt.Println(p) // 输出: {<nil> 0}// 初始化方式p = Person{"Alice", 30}fmt.Println(p) // 输出: {Alice 30}
}
内存布局
  • 结构体在内存中的布局遵循严格的对齐规则。
  • 每个字段按照其类型所需的对齐方式进行对齐。
方法

可以为结构体定义方法。

示例代码:

type Person struct {Name stringAge  int
}func (p Person) String() string {return fmt.Sprintf("%+v", p)
}func (p *Person) SetAge(age int) {p.Age = age
}func main() {p := Person{"Alice", 30}fmt.Println(p.String()) // 输出: {Name:Alice Age:30}p.SetAge(35)fmt.Println(p) // 输出: {Alice 35}
}

指针

基本概念

指针存储的是另一个变量的内存地址。

示例代码:

package mainimport "fmt"func main() {a := 10p := &a // 获取a的地址fmt.Println(*p) // 输出: 10
}
修改值

通过指针可以修改原变量的值。

示例代码:

func update(a *int) {*a = 20
}func main() {x := 5update(&x)fmt.Println(x) // 输出: 20
}

字符串

字符串不可变性

Go中的字符串是不可变的。

示例代码:

s := "hello"
// 无法直接修改s的内容
// s[0] = 'H' // 错误: 字符串是只读的
字符串操作

使用strings包进行各种操作。

示例代码:

import ("fmt""strings"
)func main() {s := "hello world"fmt.Println(strings.ToUpper(s)) // 输出: HELLO WORLD
}

切片

基本用法

切片是基于数组的一种抽象数据类型。

示例代码:

func main() {arr := [5]int{1, 2, 3, 4, 5}slice := arr[1:3] // 创建一个切片fmt.Println(slice) // 输出: [2 3]
}
动态调整大小

切片支持动态扩展。

示例代码:

func main() {s := make([]int, 0, 5)for i := 0; i < 5; i++ {s = append(s, i)}fmt.Println(s) // 输出: [0 1 2 3 4]
}
底层数组与容量

切片包含指向数组的指针、长度和容量。

示例代码:

func main() {s := []int{1, 2, 3}fmt.Println(len(s), cap(s)) // 输出: 3 3s = append(s, 4)fmt.Println(len(s), cap(s)) // 输出: 4 6

map

底层实现
  • Go语言中的map底层是一个哈希表,它由一个hmap结构体表示。
  • hmap包含两个主要部分:buckets(桶)和oldbuckets(旧桶),用于实现哈希表的扩容。
数据结构
type hmap struct {count, B, sizehint, nevacuate intflags    uint8fill     uint16noverflow uint16buckets, oldbuckets, compare, bucket, oldbucket unsafe.Pointer
}
  • count: 当前map中的元素数量。
  • B: 位数,决定了桶的数量。
  • sizehint: 初始大小提示。
  • flags: 标志位。
  • fill: 填充比例。
  • noverflow: 溢出链表的元素数量。
  • buckets: 指向当前桶的指针。
  • oldbuckets: 指向旧桶的指针。
  • compare: 比较函数。
  • bucket: 当前桶的指针。
  • oldbucket: 旧桶的指针。
桶结构
type bmap struct {overflow [1]uintptrkeys     [0]uintptrvalues   [0]uintptr
}
  • overflow: 指向溢出链表的指针。
  • keys: 存放键的数组。
  • values: 存放值的数组。
扩容过程
  • 当map的负载因子(已使用的槽位 / 总的槽位)超过一定阈值时,Go会自动扩容map。
  • 扩容时,旧的buckets会被复制到新的更大的buckets上,并重新计算哈希值以确定新位置。
删除操作

删除元素时,Go不会立即释放空间,而是标记该位置为删除状态,以便在后续的扩容过程中清理。

package mainimport ("fmt"
)func main() {m := make(map[int]string)// 添加元素m[1] = "one"m[2] = "two"m[3] = "three"// 查找元素value, ok := m[2]fmt.Println(value, ok) // 输出: two true// 删除元素delete(m, 2)_, ok = m[2]fmt.Println(ok) // 输出: false
}

channel

底层实现
  • channel本质上是一个环形缓冲区,由chan关键字声明。
  • 包含一个指向内部队列的指针、读写索引、缓冲区大小、锁等信息。
  • channel可以是带缓冲的也可以是非缓冲的,带缓冲的channel可以在不阻塞的情况下发送消息。
数据结构
type hchan struct {qcount   atomic.Value // number of items in circular queuedataqsiz int          // len of circular queuebuf      unsafe.Pointerelemsize uintptr      // bytes in each elemclosed   uint32       // closed or notelemtype *_type       // element typesendx    uint64       // send indexrecvx    uint64       // receive indexlock mutexsema    uint64
}
  • qcount: 队列中的元素数量。
  • dataqsiz: 队列的大小。
  • buf: 指向队列的指针。
  • elemsize: 元素的大小。
  • closed: 是否关闭。
  • elemtype: 元素类型。
  • sendx: 发送索引。
  • recvx: 接收索引。
  • lock: 互斥锁。
  • sema: 信号量。
同步机制
  • 非缓冲的channel在没有接收者时会阻塞发送者,反之亦然。
  • 缓冲的channel在缓冲区满时会阻塞发送者,在空时会阻塞接收者。
示例代码
package mainimport ("fmt""sync"
)func producer(ch chan int, wg *sync.WaitGroup) {defer wg.Done()for i := 0; i < 10; i++ {ch <- i}close(ch)
}func consumer(ch chan int, wg *sync.WaitGroup) {defer wg.Done()for n := range ch {fmt.Println(n)}
}func main() {ch := make(chan int, 10)var wg sync.WaitGroupwg.Add(2)go producer(ch, &wg)go consumer(ch, &wg)wg.Wait()
}

interface

底层实现
  • 在Go语言中,interface是一个特殊的类型,它允许存储任何实现了该接口的方法集的对象。
  • 实现interface的类型会在运行时动态绑定方法,这称为动态调度。
  • 每个实现了interface的类型都会有一个指向其方法表的指针,这个方法表包含了所有该类型实现的方法。
数据结构
type eface struct {_type *_typedata  unsafe.Pointer
}type iface struct {tab  *itabdata unsafe.Pointer
}
  • eface: 空接口的结构体。
  • _type: 类型信息。
  • data: 指向实际数据的指针。
  • iface: 有具体类型的接口的结构体。
  • tab: 方法表。
  • data: 指向实际数据的指针。
类型断言
  • interface{}可以存储任何类型的值,通过类型断言可以恢复原始类型。
  • 断言时,Go会检查存储的类型是否匹配目标类型,如果不匹配则会引发运行时错误。
示例代码
package mainimport ("fmt"
)type Shape interface {Area() float64
}type Rectangle struct {Width  float64Height float64
}func (r Rectangle) Area() float64 {return r.Width * r.Height
}func main() {rect := Rectangle{Width: 10, Height: 5}var shape Shape = rect// 类型断言if r, ok := shape.(Rectangle); ok {fmt.Println("Area:", r.Area())} else {fmt.Println("Not a Rectangle")}
}

方法调用

方法绑定
  • 在Go中,方法是与接收者类型绑定的函数。
  • 当调用一个方法时,编译器会生成一个带有额外参数(接收者)的函数调用。
动态调度
  • 对于接口类型的接收者,方法调用会在运行时根据实际存储的类型来决定调用哪个方法。
  • 这意味着即使在编译时不知道具体类型,只要实现了接口,就可以调用相应的方法。
示例代码
package mainimport ("fmt"
)type Shape interface {Area() float64
}type Rectangle struct {Width  float64Height float64
}func (r Rectangle) Area() float64 {return r.Width * r.Height
}func main() {rect := Rectangle{Width: 10, Height: 5}var shape Shape = rect// 调用方法fmt.Println(shape.Area()) // 输出: 50
}

更多相关信息,, https://t.me/gtokentool

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/464035.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【学习】软件测试中的过程管理为何如此重要

在软件世界的繁华盛景之中&#xff0c;无数代码编织成了璀璨的星空&#xff0c;而每一颗闪烁的星点背后&#xff0c;都离不开精心的过程管理来确保其光华不减。正如一座摩天大楼需要稳固的地基与精细的设计图一样&#xff0c;软件的成功问世同样依赖于严谨、系统的流程管控。本…

深入学习 Scrapy 框架:从入门到精通的全面指南

深入学习 Scrapy 框架&#xff1a;从入门到精通的全面指南 引言 在数据驱动的时代&#xff0c;网络爬虫成为了获取信息的重要工具。Scrapy 是一个强大的 Python 爬虫框架&#xff0c;专为快速高效地提取网页数据而设计。本文将深入探讨 Scrapy 的使用&#xff0c;从基础知识到…

【Python】【数据可视化】【商务智能方法与应用】课程 作业一 飞桨AI Studio

作业说明 程序运行和题目图形相同可得90分&#xff0c;图形显示有所变化&#xff0c;美观清晰可适当加分。 import matplotlib.pyplot as plt import numpy as npx np.linspace(0, 1, 100) y1 x**2 y2 x**4plt.figure(figsize(8, 6))# yx^2 plt.plot(x, y1, -., labelyx^2,…

Postgresql源码(137)执行器参数传递与使用

参考 《Postgresql源码&#xff08;127&#xff09;投影ExecProject的表达式执行分析》 0 总结速查 prepare p_04(int,int) as select b from tbl_01 where a $1 and b $2为例。 custom计划中&#xff0c;在表达式计算中使用参数的值&#xff0c;因为custom计划会带参数值&…

自适应对话式团队构建,提升语言模型代理的复杂任务解决能力

人工智能咨询培训老师叶梓 转载标明出处 如何有效利用多个大模型&#xff08;LLM&#xff09;代理解决复杂任务一直是一个研究热点。由美国南加州大学、宾夕法尼亚州立大学、华盛顿大学、早稻田大学和谷歌DeepMind的研究人员联合提出了一种新的解决方案——自适应团队构建&…

GitHub上传自己的项目

目录 一、安装Git插件 1&#xff09;下载 2&#xff09;安装 二、创建Gothub的创库 三、通过Git上传本地文件到Github 四、其他 1、部分指令 2、如果已经运行过git init并设置了[user]&#xff0c;下次可以直接用 一、安装Git插件 1&#xff09;下载 下载地址&#x…

SpringBoot整合EasyExcel加Vue

EasyExcel好处是什么? EasyExcel 是一个基于 Apache POI 的 Java Excel 处理库&#xff0c;主要用于高效地读写 Excel 文件。它的主要好处包括&#xff1a; 高性能&#xff1a;EasyExcel 在内存管理和读取速度上进行了优化&#xff0c;适合处理大规模 Excel 文件。 简洁易用…

VisionPro —— CogPatInspectTool对比工具

一、CogPathInspectTool工具简介 CogPathInspectTool是VisionPro重要的工具&#xff0c;主要用于缺陷检测&#xff0c;通过将当前图像与“训练图像”对比&#xff0c;获取“原始差异图像”&#xff0c;再将“原始差异图像”与“阈值图像”进行对比&#xff0c;进而获取“阈值差…

css实现antd丝带效果

先上效果图&#xff1a; 代码&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document…

BFV/BGV全同态加密方案浅析

本文主要为翻译内容&#xff0c;原文地址&#xff1a;Introduction to the BFV encryption scheme、https://www.inferati.com/blog/fhe-schemes-bgv 之前的一篇博客我们翻译了CKKS全同态加密方案的内容&#xff0c;但该篇上下文中有一些知识要点&#xff0c;作者在BFV/BGV中已…

占地1.1万平,2亿投资的智能仓储系统:高架库、AGV、码垛机器人……

导语 大家好&#xff0c;我是社长&#xff0c;老K。专注分享智能制造和智能仓储物流等内容。 我国调味料市场近年来展现出惊人的增长潜力&#xff0c;各大品牌纷纷加大投入&#xff0c;力求在竞争中脱颖而出。 广东美味鲜调味食品有限公司&#xff0c;作为行业内的佼佼者&#…

EJEAS S2滑雪对讲机全球发布会圆满举办,为滑雪市场注入新活力

时光向新&#xff0c;步履向前。站在冰雪运动与科技创新的交汇点&#xff0c;深圳爱骑仕智能科技有限公司&#xff08;以下简称“EJEAS”&#xff09;于2024年11月2日在新疆阿勒泰可可托海成功举办S2滑雪对讲机全球发布会。现场汇聚了来自全国各地的两三百名嘉宾&#xff0c;包…

个人对Numpy中transpose()函数的理解

NumPy中的transpose()函数用于对数组进行转置&#xff1a; 如果函数中不传递任何参数&#xff0c;它将进行标准的矩阵转置&#xff1b; 如果传递了一个轴序列&#xff0c;NumPy将按照这个序列重新排列轴。 二维的转置很好理解&#xff0c;就是线性代数中的矩阵转置。但高纬度…

【运动的&足球】足球运动员球守门员裁判检测系统源码&数据集全套:改进yolo11-DBBNCSPELAN

改进yolo11-FocalModulation等200全套创新点大全&#xff1a;足球运动员球守门员裁判检测系统源码&#xff06;数据集全套 1.图片效果展示 项目来源 人工智能促进会 2024.10.28 注意&#xff1a;由于项目一直在更新迭代&#xff0c;上面“1.图片效果展示”和“2.视频效果展示…

流畅!HTMLCSS打造网格方块加载动画

效果演示 这个动画的效果是五个方块在网格中上下移动&#xff0c;模拟了一个连续的加载过程。每个方块的动画都是独立的&#xff0c;但是它们的时间间隔和路径被设计为相互协调&#xff0c;以创建出流畅的动画效果。 HTML <div class"loadingspinner"><…

面试题:JVM(二)

1. 面试题 简述 Java 类加载机制?&#xff08;百度&#xff09; JVM类加载机制 &#xff08;滴滴&#xff09; JVM中类加载机制&#xff0c;类加载过程&#xff0c;什么是双亲委派模型&#xff1f; &#xff08;腾讯&#xff09; JVM的类加载机制是什么&#xff1f; &#x…

【c++日常刷题】两个数字的交集、点击消除、最小花费爬楼梯

两个数字的交集⭐ 两个数组的交集_牛客题霸_牛客网 (nowcoder.com) 题目描述&#xff1a; 解题思路&#xff1a; 通过遍历num1&#xff0c;如果遍历到的元素如果在num2中能找到&#xff0c;则这是num1和num2的公告元素&#xff1b; 这里需要借助两个数组来实现&#xff1a;…

energy 发布 v2.4.5

更新内容 修复 energy cli install 命令安装开发环境 修复 动态库加载error未暴露 增加 JS ipc.on 监听模式&#xff0c;异步返回结果 修复 energy cli 不能强制退出问题 修复 MacOS 开发模式 debug 时不更新 helper 进程 优化 energy cli 在 MacOS 开发模式和安装包制作 link…

LeetCode 19. 删除链表的倒数第 N 个结点(java)

目录 题目描述: 代码: 第一种: 第二种: 题目描述: 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], n 2 输出&#xff1a;[1,2,3,5]示例 2&#xff1a; 输入&#xff1a;h…

IMU应用于监测进食

最近&#xff0c;日本研究团队成功研发了一种创新的进食速度监测系统&#xff0c;巧妙融合IMU技术&#xff0c;旨在深入研究并有效评估个体在自由生活环境下的进食习惯。 实验中&#xff0c;科研团队把IMU传感器固定在受试者佩戴的腕带中&#xff0c;以监测并记录进食手腕时的运…