Golang database/sql源码分析Gorm是Go语言开发用的比较多的一个ORM 。它的功能比较全:
但是这篇文章中并不会直接看Gorm的源码,我们会先从database/sql分析 。原因是Gorm也是基于这个包来封装的一些功能 。所以只有先了解了database/sql包才能更加好的理解Gorm源码 。
database/sql 其实也是一个对于mysql驱动的上层封装 。”github.com/go-sql-driver/mysql”就是一个对于mysql的驱动,database/sql 就是在这个基础上做的基本封装包含连接池的使用
下面这个是最基本的增删改查操作
操作分下面几个步骤:
因为Gorm的连接池就是使用database/sql包中的连接池 , 所以这里我们需要学习一下包里的连接池的源码实现 。其实所有连接池最重要的就是连接池对象、获取函数、释放函数下面来看一下database/sql中的连接池 。
DB对象
获取方法
释放连接方法
连接池的实现有很多方法,在database/sql包中使用的是chan阻塞 使用map记录等待列表 , 等到有连接释放的时候再把连接传入等待列表中的chan 不在阻塞返回连接 。
之前我们看到的Redigo是使用一个chan 来阻塞,然后释放的时候放入空闲列表,在往这一个chan中传入struct{}{} , 让程序继续 获取的时候再从空闲列表中获取 。并且使用的是链表的结构来存储空闲列表 。
database/sql 是对于mysql驱动的封装 , 然而Gorm则是对于database/sql的再次封装 。让我们可以更加简单的实现对于mysql数据库的操作 。
liteide 怎么查看go语言自带源码包LiteIDE是一款专门为Go语言开发go语言源码怎么看的跨平台轻量级集成开发环境(IDE) , 由QT编写 。LiteIDE主要特点go语言源码怎么看:支持主流操作系统WindowsLinuxMacOSXGo编译环境管理和切换管理和切换多个Go编译环境支持Go语言交叉编译与Go标准一致的项目管理方式基于GOPAT
golang unicode/utf8源码分析包 utf-8 实现的功能和常量用于文章utf8编码,包含runes和utf8字节序列的转换功能.在unicode中,一个中文占两个字节,utf-8中一个中文占三个字节,golang默认的编码是utf-8编码,因此默认一个中文占三个字节,但是golang中的字符串底层实际上是一个byte数组.
Output:
RuneSelf该值的字节码值为128,在判断是否是常规的ascii码是使用 。hicb字节码值为191. FF 的对应的字节码为255 。
计算字符串中的rune数量,原理:首先取出字符串的码值,然后判断是不是个小于128的 , 如果是小于则直接continue.rune个数.
如果是个十六进制f1.的则是无效字符 , 直接continue.rune个数,也就是说一个无效的字符也当成一个字长为1的rune.如果字符的码值在first列表中的值和7按位的结果为其字长,比如上面示例中的 钢。其字长为三位,第一位的值为 233 .二进制形式为 11101001 ;与7按位与后的值为0.从acceptRanges中取出的结果为{locb, hicb} 。也就是标识 ox80 到 0xbf 之间的值 。而结果n也就是直接size 3跳过3个字节后,rune个数。其他函数的处理流程差不多,不再过多叙述 。
示例:
ValidString返回值表明参数字符串是否是一个合法的可utf8编码的字符串 。
RuneCount返回参数中包含的rune数量,第一个例子中将 utf8.RuneCountInString ,改成该方法调用,返回的结果相同 。错误的和短的被当成一个长一字节的rune.单个字符 H 就表示一个长度为1字节的rune.
该函数标识参数是否以一个可编码的rune开头,上面的例子中 , 因为字符串是以一个ascii码值在0-127内的字符开头,所以在执行
first[p[0]] 时,取到的是 p[0] 是72,在first列表中,127之前的值都相同都为 0xF0 ,十进制标识为240,与7按位与后值为0,所以 , 直接返回 true .
和FullRune类似,只是参数为字符串形式
golang map源码浅析 golang 中 map的实现结构为: 哈希表链表 。其中链表,作用是当发生hash冲突时,拉链法生成的结点 。
可以看到 , []bmap是一个hash table,每一个 bmap是我们常说的“桶” 。经过hash 函数计算出来相同的hash值,放到相同的桶中 。一个 bmap中可以存放 8个 元素, 如果多出8个,则生成新的结点,尾接到队尾 。
以上是只是静态文件 src/runtime/map.go 中的定义 。实际上编译期间会给它加料 ,动态地创建一个新的结构:
上图就是 bmap的内存模型,HOB Hash指的就是 top hash 。注意到 key 和 value 是各自放在一起的 , 并不是key/value/key/value/...这样的形式 。源码里说明这样的好处是在某些情况下可以省略掉 padding 字段,节省内存空间 。
每个 bmap设计成 最多只能放 8 个 key-value 对,如果有第 9 个 key-value 落入当前的 bmap , 那就需要再构建一个 bmap,通过overflow指针连接起来 。
map创建方法:
我们实际上是通过调用的makemap,来创建map的 。实际工作只是初始化了hmap中的各种字段 , 如:设置B的大小,设置hash 种子 hash 0.
注意 :
makemap返回是*hmap指针,即map 是引用对象 , 对map的操作会影响到结构体内部。
使用方式
对应的是下面两种方法
map的key的类型,实现了自己的hash 方式 。每种类型实现hash函数方式不一样 。
【go语言源码怎么看 go语言】 key 经过哈希计算后得到hash值,共 64 个 bit 位 。其中后B 个bit位置,用来定位当前元素落在哪一个桶里,高8个bit 为当前 hash 值的top hash 。实际上定位key的过程是一个双重循环的过程, 外层循环遍历 所有的overflow,内层循环遍历 当前bmap 中的 8个元素。
举例说明: 如果当前 B 的值为 5 , 那么buckets 的长度 为 2^5 = 32 。假设有个key 经过hash函数计算后,得到的hash结果为:
外层遍历bucket 中的链表
内层循环遍历 bmap中的8个 cell
建议先不看此部分内容,看完后续修改 map中元素 - 扩容操作后 再回头看此部分内容 。
扩容前的数据:
等量扩容后的数据:
等量扩容后,查找方式和原本相同 , 不多做赘述 。
两倍扩容后的数据
两倍扩容后,oldbuckets 的元素,可能被分配成了两部分 。查找顺序如下:
此处只分析mapaccess1 , 。mapaccess2相比mapaccess1 多添加了是否找到的bool值,有兴趣可自行看一下 。
使用方式:
步骤如下:
扩容条件 :
扩容的标识 : h.oldbuckets != nil
假设当前定位到了新的buckets的3号桶中,首先会判断oldbuckets中的对应的桶有没有被搬迁过 。如果搬迁过了 , 不需要看原来的桶了,直接遍历新的buckets的3号桶 。
扩容前:
等量扩容结果
双倍扩容会将old buckets上的元素分配到x,y两个部key1B == 0 分配到x部分,key1B == 1 分配到y部分
注意: 当前只对双倍扩容描述,等量扩容只是重新填充了一下元素, 相对位置没有改变 。
假设当前map 的B == 5,原本元素经过hash函数计算的 hash 值为:
因为双倍扩容之后 B = B1 , 此时B == 6 。key1B == 1, 即 当前元素rehash到高位,新buckets中 y 部分. 否则 key1B == 0 则rehash到低位 , 即x 部分 。
使用方式:
可以看到,每一遍历生成迭代器的时候 , 会随机选取一个bucket 以及 一个cell开始 。从前往后遍历,再次遍历到起始位置时,遍历完成 。
go语言源码怎么看的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于go语言、go语言源码怎么看的信息别忘了在本站进行查找喔 。
推荐阅读
- 手机高达战略游戏,手机版高达游戏
- 漫威片头手机视频壁纸安卓,漫威片头素材
- 卡点音乐下载,卡点音乐合集
- 西瓜直播间刷钻石技巧,西瓜直播一个钻石多少充值多少钱
- java唱歌评分代码 java评分功能
- js实现form转json数据,jquery form转json
- jquery获取时区,jquery获取当前日期yyyymmdd
- 亲子益智游戏设计案例,益智类亲子小游戏
- go语言exe过大 go语言报错