八股总结(go)
gorm底层怎么连接mysql的
- gorm是一个基于go语言的ORM框架,gorm不直接实现数据库的连接,而是基于Go标准库database/sql来管理数据库连接池;
- gorm.open()调用sql.open()初始化database/sql.DB;
gin框架优势
- gin是一个高性能、轻量级的web框架,基于net/http封装;
- 基于RadixTree(基数树)进行路由分配;
- 采用jsoniter进行JSON解析;
- API设计简洁,内置多种HTTP方法,参数解析简洁;
- 有着强大的中间件机制,支持局部和全局中间件,内置多个常用中间件,例如:
- CORS(跨域处理)
- JWT认证
- 限流
- 日志记录
- 错误恢复(recovery,避免程序崩溃,能够自动捕获panic并返回500错误)
- 内置渲染引擎,支持HTML模板渲染也支持JSON、XML、YAML格式;
切片的底层原理
- slice本质是对底层数组的抽象,包含三个字段,指针:指向底层数组的起始地址,长度:切片当前长度,容量:表示切片当前容量;
- 当切片容量不足时,会创建一个新的底层数组,并将数据拷贝到新的数组中,如果当前容量cap<=1024扩容两倍,如果当前容量>1024,扩容1.25倍左右;
- 切片的共享机制,切片和数组是共享底层存储的,切片的修改会影响原始数组,slice[i:j]创建的新的切片如果修改数据,原slice仍然也会被修改;
Map的底层原理
- map采用哈希表(hashtable)结构,底层包含桶数组:存储键值对,哈希函数:用于计算key的哈希值并确定存放的bucket,溢出桶:当桶满时存储额外的数据;
- go使用链地址法+开放寻址法解决哈希冲突,链地址法:每个桶最多存储8个键值对,如果超过8,会创建溢出桶,开放寻址法:使用额外的哈希计算在多个同种寻找空位存储;
- map的扩容,当map大于负载因子6.5时触发扩容,创建2倍的桶,并重新计算key的哈希值,重新分配位置,采用渐进式迁移,为了避免一次性的拷贝影响性能;
- map的删除,不会立即回收内存,只是标记删除,如果删除后桶为空,也不会回收桶的内存,当map进行扩容或更多数据加入时,才会真正释放内存;
将切片与map传入函数中,对数据进行修改,在函数外部切片与map会改变吗
- 切片是引用传递,本质上是一个结构体,函数接收到还是这个结构体的副本,但其指向底层数组的指针不变,如果修改其数据会影响函数外的原切片,但若改变切片长度append()触发了扩容机制,则副本指向的底层数组地址发生改变,此时原切片则不会改变。如果切片触发扩容也能修改生效,则需要返回新的切片;
- map是引用传递,本质上是一个指针,指向底层的哈希表,函数内部的修改会直接影响外部的map,如果在函数内部对map进行重新赋值(make(map[string]int)),入参会指向新的map,但不会影响外部的map;如果想要在函数内的重新赋值,则可以使用指针类型进行传参;
切片创建方式有哪些
直接声明:var s []int,默认值为nil, 不能通过索引访问,会发生panic报错但可以append;
使用make([]int, 5),创建长度为5容量为5默认数据为0的切片,也可以通过make([]int, 3, 10)指定capacity;
直接初始化,s := []int{1, 2, 3};
可以通过数组或现有切片创建,arr[1:4],共享arr数组或切片的底层存储,len()是数据长度,cap则是其arr[1]到arr末尾的长度,即从主切片中取出指向开头位置的链表地址这个意思;
s1 := []int{10, 20, 30, 40, 50} s2 := s1[1:3] // [20, 30] fmt.Println(s2, len(s2), cap(s2)) // [20 30] 2 4
赋值切片(copy()),如果想要创建一个独立的新切片,避免共享底层数组,可以使用copy(),
src := []int{1, 2, 3} dst := make([]int, len(src)) copy(dst, src)