1.defer执行顺序
先定义,后执行
defer在panic之前执行
defer虽然是在return的时候才执行,但是如果参数是函数,会先执行参数,并且把结果放到调用栈里面
2.for循环的时候千万不要用tmp的指针
3.array赋值是只拷贝
func main() {
c := [3]int{1, 2, 3}
d := c
c[0] = 999
fmt.Println(d) // 输出[1, 2, 3]
}
c[0]不会修改d
slice数据结构:
- array
- len
- cap
slice底层是指向一个固定大小的数组,当容量够的时候不会扩容,会忘数组中添加数据;当容量不够的时候,先扩容。
4.静态语言和动态语言
静态语言:如果在编译的时候就知道变量的类型,则是静态语言,优点是编译器可以在编译阶段做一些类型检查。例如:c,c++,java,go
动态语言:在编译的时候不知道变量类型,因此检查变量类型需要再运行时做。一般是脚本语言,优点是开发快,但是维护难。比如:python,php,javascript
5.使用Go的好处
- 语言层面支持并发。并且并发度特别高
- 内置GC
- 简单易学
- 代码格式强一致
- 跨平台
6.go什么时候会发生内存逃逸golang程序变量
会携带有一组校验数据,用来证明它的整个生命周期是否在运行时完全可知。如果变量通过了这些校验,它就可以在栈上
分配。否则就说它 逃逸
了,必须在堆上分配
- 在方法内把局部变量作为指针返回。
- 发送指针到channel
- 切片的元素是指针
- 切片重新分配大小
- 在interface类型的变量上调用方法
7.拷贝大切片比小切片的代价大吗?
不大,代价是一样的。因为切片底层结构是三个属性:1个指向data的指针和2个int类型的属性,切片的拷贝如果不扩容,只会是这三个属性的值拷贝。代价与切片容量和元素的多少无关
8.unsafe.Pointer与uintptr的区别
unsafe.Pointer只是单纯的通用指针类型,用于转换不同类型指针,它不可以参与指针运算;
而uintptr是用于指针运算的,GC 不把 uintptr 当指针,也就是说 uintptr 无法持有对象, uintptr 类型的目标会被回收
unsafe.Pointer 可以和 普通指针 进行相互转换
unsafe.Pointer 可以和 uintptr 进行相互转换
9.mysql为什么用B+树
与B树比较,有三点优势:
- 所有数据都在叶子节点,非叶子节点相当于是一个稀疏索引。这样非叶子节点就比较小,一个数据页上可以存放更多的非叶子节点,减少磁盘io
- B+树所有叶子节点都连起来了,比B树更容易遍历。B树遍历需要用到中序遍历
- 适合范围查询。由于B树非叶子节点也保存了数据,因此不好做范围查询