面试下来我感觉我都讲出来了,算法题也写出来了,但是二面完一查结果就直接淘汰了。这个B是不是不招人啊。。

Go的GMP模型

可以重用
逻辑处理单元P 和 M 的这种关系就相当于 Linux 系统中的用户层面的线程和内核的线程是一样的
GMP

GO的GC

on-the-fly

原理如下

stop the worldstop the worldwritebarrier
on-the-fly

简化步骤如下:1、首先创建三个集合:白、灰、黑。

白色灰色
A、F
3
灰色对象引用的对象白色集合灰色集合

5、重复 4 直到灰色中无任何对象

write-barrier

由于这个EGH并没有和RootSet有直接或是间接的关系,所以就会被清除。

7、收集所有白色对象(垃圾)

直接相关间接相关

Go的map底层是怎么实现的?

map 的底层是一个结构体

// Go map 的底层结构体表示
type hmap struct {
    count     int    // map中键值对的个数,使用len()可以获取 
 flags     uint8
 B         uint8  // 哈希桶的数量的log2,比如有8个桶,那么B=3
 noverflow uint16 // 溢出桶的数量
 hash0     uint32 // 哈希种子

 buckets    unsafe.Pointer // 指向哈希桶数组的指针,数量为 2^B 
 oldbuckets unsafe.Pointer // 扩容时指向旧桶的指针,当扩容时不为nil 
 nevacuate  uintptr        

 extra *mapextra  // 可选字段
}

const (
 bucketCntBits = 3
 bucketCnt     = 1 << bucketCntBits     // 桶数量 1 << 3 = 8
)

// Go map 的一个哈希桶,一个桶最多存放8个键值对
type bmap struct {
    // tophash存放了哈希值的最高字节
 tophash [bucketCnt]uint8
    
    // 在这里有几个其它的字段没有显示出来,因为k-v的数量类型是不确定的,编译的时候才会确定
    // keys: 是一个数组,大小为bucketCnt=8,存放Key
    // elems: 是一个数组,大小为bucketCnt=8,存放Value
    // 你可能会想到为什么不用空接口,空接口可以保存任意类型。但是空接口底层也是个结构体,中间隔了一层。因此在这里没有使用空接口。
    // 注意:之所以将所有key存放在一个数组,将value存放在一个数组,而不是键值对的形式,是为了消除例如map[int64]所需的填充整数8(内存对齐)
    
    // overflow: 是一个指针,指向溢出桶,当该桶不够用时,就会使用溢出桶
}
 k 的 hash 值与 buckets 长度取余

遍历map是有序的吗?为什么?

随机值序号随机的 cell 按序遍历 bucket
扩容

map作为函数是什么传递?

map 传的是地址值

在函数里面修改map会影响原来的吗?

会的,因为传递的map的地址,会对原来的map进行修改。

func TestMap(t *testing.T) {
 a := make(map[int]int)
 a[0] = 1
 fmt.Println(a)
 changeMap(a)
 fmt.Println(a)
}

func changeMap(b map[int]int) {
 b[0] = 2
}

结果如下

那数组呢?

数组不会,数组不是引用类型,传的值传递,并不是应用传递。

func TestArray(t *testing.T) {
 a := [3]int{1, 2, 3}
 fmt.Println(a)
 changeArray(a)
 fmt.Println(a)
}

func changeArray(a [3]int) {
 a[0] = 1
}
结果

切片呢?

会,和 map 一样,都是引用类型。传递的是地址。

func TestSlice(t *testing.T) {
 a := make([]int, 3, 3)
 a[0] = 1
 a[1] = 2
 a[2] = 3
 fmt.Println(a)
 changeSlice(a)
 fmt.Println(a)
}

func changeSlice(a []int) {
 a[0] = 4
}
结果

linux有用过是吧?如何查看一个服务是否在运行?

ps -ef | grep 服务名 或 ps aux |grep 服务名lsof -i:端口号systemctl status 服务名 或 service 服务名 statusnetstatnetstat -tnlp 

我只知道这个文件名,能找到这个文件在哪里吗?

可以使用 find 命令

find / -name "main.go"

用过mysql是吧?mysql 索引说一下?

mysql 的索引包括** 基于InnoDB的聚集索引、基于MyISAM的非聚集索引、primary key 主键索引、secondary key 次要索引**

叶子结点会存储数据行数据和索引在一起数据和索引不在一起MyISAM可以没有唯一标识数据记录的列作为主键同样用 B+Tree,data域存储相应记录主键的值而不是地址

死锁是怎么产生的

产生死锁就有四个必要条件:互斥条件、请求和保持条件、不剥夺条件、环路等待条件。

了解分布式锁吗?讲讲红锁?

只磕磕绊绊讲了一些分布式锁,红锁就不太记得了(

可以看看这篇博客 基于Go语言的分布式红锁

算法:反转链表。这写不出来的话,就说不过去了。

TCP和UDP区别?

TCP 是可靠传输,面向连接,基于流,占用资源多,效率低。

UDP是尽最大努力交付,基于无连接,基于报文,UDP 占用系统资源较少,效率高。

TCP是可靠传输,为什么还有丢包的情况?

丢包是网络问题,TCP的可靠是可靠在如果发生丢包,那么会立即重传报文段。

UDP能实现可靠传输吗?怎么实现?

可以的,我们只需要仿照TCP的可靠传输机制就可以了,比如说设置ACK确认机制,一旦没有收到,或是收到三次上一个报文的ACK,我们就立即重传丢失的报文。再比如说设置滑动窗口来保证数据传输的安全性等等...

TCP和IP的区别是什么?

TCP 是传输控制协议(Transmission Control Protocal),是基于IP的传输层协议,是传输层的,IP 是因特网协议(Internet Protocol)在网络层的。

四次挥手的细节?

ESTABLISHED
FIN1seq=u1FIN-WAIT-1(终止等待1)

注意:TCP规定,FIN报文段即使不携带数据,他也消耗掉一个序号!!

ack = u + 1v最后一个字节的序号加1CLOSE-WAIT(关闭等待)FIN-WAIT-2(终止等待2)FIN = 1wack = u + 1LAST-ACK(最后确认)ACK置1ack=w+1seq=u+1TIME-WAIT还没有还没有释放掉2MSL

时间MSL叫做最长报文段寿命,RFC793建议设在两分钟。但是在现在工程来看两分钟太长了,所以TCP允许不同的实现可以根据具体情况使用更小的MSL值。

四次握手

为什么 time_wait 是2MLS?

B会超时重传这个FIN+ACK报文段,而A就能在 2MSL 时间内收到这个重传的FIN+ACK报文段如果A在TIME-WAIT状态不等待一段时间,而实发送完ACK报文段后立即释放连接,那么就无法收到B重传的FIN+ACK报文段,因而也不会再发送一次确认报文段B只要收到了A发出的确认,就进入CLOSED状态

大量处于 close wait 的是什么场景? 如何解决?

通常出现大量的CLOSE_WAIT,说明Server端没有发起close()操作,这基本上是用户server 端程序的问题了;

通常情况下,Server都是等待Client访问,如果Client退出请求关闭连接,server端自觉close()对应的连接。

一般是程序 Bug,或者关闭 socket 不及时。服务端接口耗时较长,客户端主动断开了连接,此时,服务端就会出现 close_wait。

这个我们就只能检查自己代码了,用netstat或是其他工具,检测代码为啥耗时长。

cookie和session有什么区别?

cookie和session的共同之处在于:cookie和session都是用来跟踪浏览器用户身份的会话方式。cookie数据保存在客户端,session数据保存在服务器端。

你是用go的是吧?chan用过吧?那说说对一个关闭的chan做读写会发生什么操作?为什么?

如果有元素,就继续读剩下的元素,如果没有就是这个chan类型的零值,比如整型是 int,字符串是 ""src/runtime/chan.go

map 的底层说一下?

看上面

如果你这个项目,我突然有一个时间段,多了很多流量,要怎么处理?

  1. 我们要延长一些 token,cookie的设置时间,或是设置这些过期时间不一样,防止缓存雪崩的情况。
  2. 设置布隆过滤器,防止缓冲击穿情况。
  3. 使用 nginx 进行 http/https 的流量分发。使用轮询,随机,哈希,一致性哈希等等进行负载均衡等等...
  4. 提高服务自身性能,比如sql的索引,语法层面的调参等等...
  5. 引入CDN进行加速。
  6. 提高服务器配置。
  7. ...

算法:连续子序列的最大和

[1] https://blog.csdn.net/Peerless__/article/details/125458742