文章目录

  • 写在前面
  • 笔试
  • 一面
    • 线程和进程有什么区别?各自有什么优缺点?
    • 进程之间如何进行通信?
    • 什么是信号,信号量是如何实现的?
    • 讲讲Go里面的GMP模型?
    • Go的GMP模型
    • map用过吧?怎么对map进行排序?
    • 讲讲map底层?为什么是无序的?
    • 知道TCP连接吧?三次握手的目的是什么?
    • 那四次挥手有了解过吗?为什么是四次?
    • 什么是粘包和拆包?为什么会出现?
    • 怎么解决?
    • 什么是事务?
    • 那 redis 支持事务吗?
    • 算法:手撕链表,要求递归实现。
    • 算法:忘记了。。好像是中等题,反正不难,也不简单。
  • 二面

写在前面

米哈游 面试下来感觉还行吧,挺注重基础的,面试官水平也很高。但是感觉不是在招人的样子,我有好多同学都是简历挂(

笔试

无笔试,很奇怪(

一面

线程和进程有什么区别?各自有什么优缺点?

进程 线程
系统中正在运行的一个应用程序 系统分配处理器时间资源的基本单元
程序一旦运行就是进程 进程之内独立执行的一个单元执行流
资源分配的最小单位 程序执行的最小单位

进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。

线程有自己的堆栈和局部变量,但线程没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些 要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程

进程之间如何进行通信?

管道、消息队列、共享内存、信号量、信号、socket

什么是信号,信号量是如何实现的?

信号:
在Linux中,为了响应各种事件,提供了几十种信号,可以通过kill -l命令查看。

如果是运行在 shell终端 的进程,可以通过键盘组合键来给进程发送信号,例如使用Ctrl+C 产生SIGINT 信号,表示终止进程。

如果是运行在后台的进程,可以通过命令来给进程发送信号,例如使用kill -9 PID 产生SIGKILL信号,表示立即结束进程。

信号量:

当使用共享内存的通信方式,如果有多个进程同时往共享内存写入数据,有可能先写的进程的内容被其他进程覆盖了。

因此需要一种保护机制,信号量本质上是一个整型的计数器,用于实现进程间的互斥和同步

信号量代表着资源的数量,操作信号量的方式有两种:

  • P操作:这个操作会将信号量减一,相减后信号量如果小于0,则表示资源已经被占用了,进程需要阻塞等待;如果大于等于0,则说明还有资源可用,进程可以正常执行。
  • V操作:这个操作会将信号量加一,相加后信号量如果小于等于0,则表明当前有进程阻塞,于是会将该进程唤醒;如果大于0,则表示当前没有阻塞的进程。

讲讲Go里面的GMP模型?

Go的GMP模型

G:表示goroutine,存储了goroutine的执行stack信息、goroutine状态以及goroutine的任务函数等;另外G对象是可以重用的。
P:表示逻辑processor,P 的数量决定了系统内最大可并行的 G 的数量(前提:系统的物理cpu核数 >= P的数量);P的最大作用还是其拥有的各种G对象队列、链表、一些cache和状态。
M:M 代表着真正的执行计算资源,物理 Processor。

G 如果想运行起来必须依赖 P,因为 P 是它的逻辑处理单元,但是 P 要想真正的运行,他也需要与 M 绑定,这样才能真正的运行起来,P 和 M 的这种关系就相当于 Linux 系统中的用户层面的线程和内核的线程是一样的

map用过吧?怎么对map进行排序?

go的map不保证有序性,所以按key排序需要取出key,对key排序,再遍历输出value

讲讲map底层?为什么是无序的?

map 的底层是一个结构体

// Go map 的底层结构体表示
type hmap struct {count     int    // map中键值对的个数,使用len()可以获取 flags     uint8B         uint8  // 哈希桶的数量的log2,比如有8个桶,那么B=3noverflow uint16 // 溢出桶的数量hash0     uint32 // 哈希种子buckets    unsafe.Pointer // 指向哈希桶数组的指针,数量为 2^B oldbuckets unsafe.Pointer // 扩容时指向旧桶的指针,当扩容时不为nil nevacuate  uintptr        extra *mapextra  // 可选字段
}const (bucketCntBits = 3bucketCnt     = 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: 是一个指针,指向溢出桶,当该桶不够用时,就会使用溢出桶
}


当向 map 中存储一个 kv 时,通过k 的 hash 值与 buckets 长度取余,定位到 key 在哪一个bucket中,hash 值的高8位存储在 bucket 的 tophash[i] 中,用来快速判断 key是否存在。当一个 bucket 满时,通过 overflow 指针链接到下一个 bucket。

在源码runtime.mapiterinit

func mapiterinit(t *maptype, h *hmap, it *hiter) {...it.t = tit.h = hit.B = h.Bit.buckets = h.bucketsif t.bucket.kind&kindNoPointers != 0 {h.createOverflow()it.overflow = h.extra.overflowit.oldoverflow = h.extra.oldoverflow}r := uintptr(fastrand())if h.B > 31-bucketCntBits {r += uintptr(fastrand()) << 31}it.startBucket = r & bucketMask(h.B)it.offset = uint8(r >> h.B & (bucketCnt - 1))it.bucket = it.startBucket...mapiternext(it)
}

通过对mapiterinit 方法阅读,可得知其主要用途是在 map 进行遍历迭代时进行初始化动作。共有三个形参,用于读取当前哈希表的类型信息、当前哈希表的存储信息和当前遍历迭代的数据

源码中 fastrand

...
// decide where to start
r := uintptr(fastrand())
if h.B > 31-bucketCntBits {r += uintptr(fastrand()) << 31
}
it.startBucket = r & bucketMask(h.B)
it.offset = uint8(r >> h.B & (bucketCnt - 1))// iterator state
it.bucket = it.startBucket

在这段代码中,它生成了随机数。用于决定从哪里开始循环迭代。更具体的话就是根据随机数,选择一个桶位置作为起始点进行遍历迭代。

因此每次重新for range map,你见到的结果都是不一样的。那是因为它的起始位置根本就不固定!

知道TCP连接吧?三次握手的目的是什么?

因为通信的前提是确保双方都是接收和发送信息是正常的。
三次握手是为了建立可靠的数据传输通道
第一次握手就是让 接收方 知道 发送方 有发送信息的能力
第二次握手就是让 发送方 知道 接收方 有发送和接受信息的能力
第三次握手就是让 接收方 知道 发送方 有接受信息的能力

那四次挥手有了解过吗?为什么是四次?

四次挥手则是为了保证等数据完成的被接收完再关闭连接。

既然提到需要保证数据完整的传输完,那就需要保证双方 都达到关闭连接的条件才能断开。

第一次挥手:客户端发起关闭连接的请求给服务端;

第二次挥手:服务端收到关闭请求的时候可能这个时候数据还没发送完,所以服务端会先回复一个确认报文,表示自己知道客户端想要关闭连接了,但是因为数据还没传输完,所以还需要等待;

第三次挥手:当数据传输完了,服务端会主动发送一个FIN 报文,告诉客户端,表示数据已经发送完了,服务端这边准备关闭连接了

第四次挥手:当客户端收到服务端的 FIN 报文过后,会回复一个ACK 报文,告诉服务端自己知道了,再等待一会就关闭连接。

什么是粘包和拆包?为什么会出现?

粘包就是两个或者多个以上的包粘在一起,拆包就是为什么解决粘包问题。

出现粘包原因有两个,一个是发送方发送不及时,导致多个包在发送端粘黏。另一个是接收方接受不及时,导致包在接收端堆叠导致。

怎么解决?

设计一个带包头的应用层报文结构就能解决。包头定长,以特定标志开头,里带着负载长度,这样接收侧只要以定长尝试读取包头,再按照包头里的负载长度读取负载就行了,多出来的数据都留在缓冲区里即可。其实ip报文和tcp报文都是这么干的。

什么是事务?

事务具有原子性、一致性、隔离性、持久性特性,并且 指将一系列数据操作捆绑成为一个整体进行统一管理,如果某一事务执行成功,则在该事物中进行的所有数据更改均会提交,成为数据库中的永久组成部分。

那 redis 支持事务吗?

redis 是不支持事务的,因为 他不支持原子性,但是支持一致性,是最终一致性。

算法:手撕链表,要求递归实现。

算法:忘记了。。好像是中等题,反正不难,也不简单。

二面

我以为过了简历,免了笔试,一面算法写出来,八股也能吹了,应该有二面,但还是挂了(

真的是 海量 hc 吗。。。

【Golang开发面经】米哈游(一轮游)相关推荐

  1. 【Golang开发面经】360(一轮游)

    文章目录 写在前面 笔试 一面 TCP 和 UDP 区别 UDP能可靠传输吗? MYSQL的隔离等级 左连接,右连接有什么区别? JOIN的性能一定好吗? 线程的通信方式? 快排原理?堆排呢? 算法: ...

  2. 【Golang开发面经】深信服(两轮技术面)

    文章目录 写在前面 一面 了解过切片和数组吗?有什么区别? 那这样初始化可以吗?有什么问题? 用过map吧?怎么遍历map? 那遍历 map 是有序的吗? 为什么是无序的? 用过chan吧?怎么声明一 ...

  3. 【Golang开发面经】字节跳动(三轮技术面)

    文章目录 写在前面 笔试 一面 epoll.select.poll 区别 epoll 的水平触发和边缘触发的区别 TCP 的流量控制 为什么有了流量控制还要有拥塞控制? TCP 不是可靠传输吗?为什么 ...

  4. 【Golang开发面经】蔚来(两轮技术面)

    文章目录 一面 1. channel 缓冲与非缓冲 2. mysql引擎 3. 索引如何建立? 4. linux 如何看进程 5. redis 字符串的底层 6. 线程池理解 7. 线程池的拒绝策略 ...

  5. 【Golang开发面经】知乎(两轮技术面)

    文章目录 写在前面 笔试 一面 进程和线程的区别? 虚拟地址是什么? 内存分段分页讲讲? http 1.0,1.1,2.0 区别? post和get的区别 TCP 连接是怎么样的? 为什么是三次?断开 ...

  6. 【Golang开发面经】B站(两轮技术面)

    文章目录 写在前面 笔试 一面 Go的GMP模型 GO的GC Go的map底层是怎么实现的? 遍历map是有序的吗?为什么? map作为函数是什么传递? 在函数里面修改map会影响原来的吗? 那数组呢 ...

  7. php开发面试题---php面向对象详解(对象的主要三个特性)

    php开发面试题---php面向对象详解(对象的主要三个特性) 一.总结 一句话总结: 对象的行为:可以对 对象施加那些操作,开灯,关灯就是行为. 对象的形态:当施加那些方法是对象如何响应,颜色,尺寸 ...

  8. php开发面试题---攻击网站的常用手段有哪些,及如何预防(整理)

    php开发面试题---攻击网站的常用手段有哪些,及如何预防(整理) 一.总结 一句话总结: 比较记忆:注意比较各种攻击的区别,比如csrf和xss,以及xss和sql,这样才能记住 1.Sql注入是什 ...

  9. c++软件开发面试旋极面试题_经典软件开发面试题:浏览器中输入一个网址后发生了什么?...

    经典软件开发面试题:浏览器中输入一个网址后发生了什么? ​ 大家好, 这一期呢,我们来谈一个经典的面试题.这种题目是在浏览器中输入一个网址以后, 会显示一个网页,这期间到底发生了什么? 答案要求说的越 ...

最新文章

  1. node.js中模块_在Node.js中需要模块:您需要知道的一切
  2. 关于人脸识别滥用的十个可能的应对方案
  3. 通过Http管理Solr Core,实现索引的分类
  4. 踏上《软件设计精要与模式》第二版的征途
  5. 笔记-项目采购管理-复习要点
  6. python3利用smtplib通过qq邮箱发送邮件
  7. java小编程----str中没有内容
  8. Jquery ajax提交表单几种方法详解
  9. 一文彻底搞懂前端监控 等推荐
  10. c语言凸包算法,基于C语言的凸包算法实现
  11. UVA3942 Remember the Word
  12. Thinking in C++ Notes 常量
  13. Axis2发布webservices
  14. 手机通过笔记本电脑上网
  15. k2p华硕系统怎么设置_双频路由器怎么设置网速快(k2p刷华硕怎么设置网速好)
  16. 【设计】同步降压型DC-DC转换器驱动电路设计
  17. OSN8800 华为单板
  18. c语言查看cpu温度代码_C语言获取CPU核心温度
  19. css radial-gradient绘制渐变背景
  20. TP5.1升级到ThinkPHP6.0的实战教程看云版

热门文章

  1. Cocos论坛九问九答
  2. 【校园卡】2021年开学季三大运营商校园卡最近消息!
  3. 网易有道2013年校园招聘面试二面试题-项目安排
  4. 【图解】联想IdeaPad V450拆机教程,光驱位安装固态硬盘图解
  5. 毕业论文-----有关页码的全部问题
  6. java读取dat_Java批量解析微信dat文件
  7. 微信智能硬件应用——微信插座控制
  8. 腾讯安心生态联盟正式成立 联动伙伴开放技术助力“数字兴农”
  9. 6代之后的CPU安装win7的方法
  10. 实现邮箱验证功能的代码