01-Golang基础

01-Golang基础
菠萝Golang基础知识
根据本人知识进行持续更新中…
OOP
[面试题]、说说你对面相对象的理解
如何回答呢?
首先我们肯定要讲出面向对象的三个特性:a.封装 b.继承 c.多态
接下来我们详细说一下这三个特性。
封装:封装的意义,在于明确标识出允许外部使用的所有成员函数和数据项,或者叫接口。
继承:
继承基类的方法,并做出自己的扩展;
声明某个子类兼容于某基类(或者说,接口上完全兼容于基类),外部调用者可无需关注其差别(内部机制会自动把请求派发dispatch到合适的逻辑)。多态:基于对象所属类的不同,外部对同一个方法的调用,实际执行的逻辑不同。很显然,多态实际上是依附于继承的第二种含义的。
其实一般说到这里就可以了,当然我们也可以举一些例子。(其实对于封装和继承很好理解,这个例子基本上不用,那么我们可以举一些多态的例子)
什么是多态呢?这时候我们可以举一下子,重写和重载。基本上把这两个说好就可以了。
slice
当前引用下会把相关面试问题回答,后续是一些相关知识
[面试题一]、slice的扩容过程?
对于这个问题,我们要理清思路,讲到扩容,对于slice这种比较简单的结构:
- 讲一下slice的数据结构,它有三个字段, array(一个指针,指向底层的数组),len(当前slice里面存放的个数),cap(就是当前slice的容量,最多存放多少数据)
- 接下来,讲一下。什么情况下发生扩容,必然是当我们调用 append()函数,向slice中添加数据的时候,才会出现,存放不下的情况,那么我们就需要扩容了。
- 接下来,就是需要讲扩容的规则(这部分网上基本上都有,我们可以简述一下扩容规则,注意,其实在双倍扩容的时候会去比较,cap+newNum > 2*cap,如果大于,则直接newCap=cap+newNum)
- golang1.18版本之前:当 cap < 1024的时候,采用双倍扩容;当 cap > 1024的时候,采用1.25倍的扩容机制。
- golang1.18版本之后:当 cap < 256的时候,采用双倍扩容;当 cap > 256的时候,采用 newCap = oldCap + (oldCap+3*256)/4。
- 最后,我们可以再说一下,其实在go中,由于内存对齐机制的存在,容扩最后会调用,runUpSize()最终来计算得到,计算结果一般要 >= 之前的cap。
[面试题二]、slice和array的区别
这个问题基本上是送分的,对于slice简单回答一下就好:
- slice的底层数组就是数组,slcie是对数组的封装,它描述一个数组的片段
- 数组是定长的,长度定义好之后,不能再改变
- 数组就是一片连续的内存,slcie实际上是一个结构体,它包含三个字段:长度、容量、底层数组。
slcie相关知识点
- slice 的底层数据是数组,slice 是对数组的封装,它描述一个数组的片段
- 数组是定长的,长度定义好之后,不能再更改。
- 数组就是一片连续的内存, slice 实际上是一个结构体,包含三个字段:长度、容量、底层数组。
// runtime/slice.go |
map
[面试题一]、map的扩容过程
对于Map的扩容,首先我们需要知道map的数据结构:
- 可以简单介绍一下,map的设计(hamp、bmap,其中hmap的字段:buckets,oldbuckets可以讲一下,这个其实就是 我们所说的桶,它们都是bmap的切片,我们搜索大数据最终存储在bmap上,接着讲一下 bmap的数据结构 ==> tophash、keys、values、pad、overflow这几个可以简单介绍一下)
- 讲完数据结构,接下来讲一下,扩容的触发条件 。其扩容的触发,又和2种扩容有关
- 双倍扩容:当负载因子大小 > 6.5
- 等量扩容:当overflow的buckets数量过多的时候,会触发,也就是 bucket 总数 2^B 小于 2^15 时,如果 overflow 的 bucket 数量超过 2^B;当 B >= 15,也就是 bucket 总数 2^B 大于等于 2^15,如果 overflow 的 bucket 数量超过 2^15。