小西科技 - 2025转正实习 - golang开发
基本信息
- 面试岗位:Go语言开发(客户方向研发)
- 面试形式:技术面试
- 主要考察方向:Go语言基础、并发编程、网络协议、Linux系统
一、Go语言基础
- 协程与进程/线程的区别 面试官问题:在Go语言中有一个概念叫协程,协程和我们一般聊的进程线程有什么区别吗?
面试者回答:
- 进程是操作系统资源分配的最小单位
- 线程是操作系统内核调度的最小单位
- 协程是Go语言中用户态的并发编程技术,通过GMP模型进行调度
- 内存空间方面:进程有独立内存空间,相互隔离;线程共享地址空间;Go协程通过channel进行通信
评价:回答基本正确,表述清晰。
- GMP模型 面试官问题:你刚刚说到GMP模型,你能简单描述一下这个吗?
面试者回答:
- GMP模型是Go运行时的协程调度模型
- P代表Processor(CPU处理器)
- M代表Machine(操作系统线程)
- G代表Goroutine(Go协程)
- 协程任务放入工作队列,线程由Go运行时启动,动态与协程绑定,交给CPU内核并发执行
面试官追问:每个M下面都有多个G,假如当前执行的G被阻塞了,那么这个G它会被放到哪里?
面试者回答:会向其他工作队列去抢占任务执行,因为它是可抢占式的。
评价:回答基本正确。GMP模型解释清晰,但关于阻塞G的处理回答不够完整。实际上,当G被阻塞时,M会与P解绑,阻塞的G会被放到等待队列,P可以绑定新的M继续执行其他G。
- 协程数量与协程池 面试官问题:一个进程能启动多少个Go协程?既然协程开销比较小,为什么还要使用协程池?
面试者回答:
- Go协程占用内存空间小,可以动态增长,切换开销小
- 一个进程可以起上万个协程,具体取决于执行工作内容
- 协程池主要是为了省去协程的创建和销毁开销,实现协程复用
评价:回答正确。协程初始栈大小约2KB,可以动态增长,理论上一个进程可以创建数十万甚至上百万协程(受限于系统资源)。
- 协程间通信方式 面试官问题:协程间通信有哪些方式?
面试者回答:
- 使用全局变量(需注意并发安全,进行资源控制)
- 使用context上下文控制协程行为
- 使用channel进行通信
评价:回答正确且完整。
- Channel相关问题 面试官问题:带缓冲区的channel和无缓冲的channel有什么区别?
面试者回答:
- 带缓冲的channel实现生产者消费者模型
- 有缓冲时,发送者可以直接向缓冲区发送资源而不必等待接收者
- 无缓冲channel需要发送和接收双方同时准备好,否则会阻塞
面试官问题:对一个没有初始化的channel进行写入有什么影响?
面试者回答:未初始化的channel是空指针,进行读写操作会引发panic。
面试官补充:对已关闭的channel进行写入会发生panic,但读取不会出错。
面试官问题:如何判断channel是否已关闭?
面试者回答:不太清楚(面试官解释:读取channel时可以使用第二个返回值判断,如data, ok := <-ch
,当ok为false时表示channel已关闭且无数据)
评价:基本回答正确,但对已关闭channel的读取机制理解不够深入。
- 任务分批执行设计 面试官问题:有10个任务需要分批次执行(每次最多2个),全部完成后进行统计,如何设计代码?
面试者回答:
- 使用协程池,工作协程数量设为2
- 使用生产者消费者模型,通过channel传输任务
- 使用计数器(wg.WaitGroup)判断任务是否全部完成
面试官追问:如何判断10个任务已经全部结束?
面试者回答:通过WaitGroup,每个任务完成时计数器减一,当计数器为0时表示任务全部完成。
评价:回答正确且实用,展示了对并发控制的理解。
- 切片和Map未初始化操作 面试官问题:对未初始化的切片或map进行操作会panic吗?
面试者回答:
- 未初始化的map进行写入会报错
- 切片未初始化时使用append也会报错
面试官纠正:
- 未初始化的map进行写入确实会panic
- 但未初始化的切片(
var s []int
)使用append不会panic,因为编译器会自动处理初始化和扩容
评价:对map的理解正确,但对切片的理解有误。这是常见误区,需要特别注意。
- Go接口实现 面试官问题:定义一个接口后,如何表明一个结构体实现了该接口?
面试者回答:Go中接口实现是隐式的,只要结构体实现了接口的所有方法,就视为实现了该接口。
评价:回答正确且简洁。
- Go泛型 面试官问题:之前有了解过Go语言的泛型吗?
面试者回答:泛型比较新,在之前项目中用接口实现类似功能,对泛型具体写法只简单了解。
评价:诚实回答,表明了实际经验。
二、网络协议
- TCP和UDP区别 面试官问题:TCP协议和UDP协议的区别是什么?
面试者回答:
- TCP是经过三次握手、四次挥手建立的可靠面向连接的通信
- UDP是单向、不可靠、无连接的协议
- TCP有拥塞控制、流量控制等高级特性,UDP没有
评价:回答正确。
- UDP报文大小限制 面试官问题:UDP单次传输的报文有最大限制吗?
面试者回答:UDP应该有最大长度限制,因为大UDP包对网络状况和接收方压力大。
评价:回答基本正确。UDP数据报最大理论长度为65535字节(包括头部),但实际受MTU限制,通常不超过1500字节(以太网)。
- TCP粘包问题 面试官问题:TCP中的粘包是什么概念?有哪些解决方案?
面试者回答:
- TCP是流式传输协议,无法保证数据包的区分度,可能导致数据包粘在一起
- 解决方案:使用分隔符(如特定符号)区分数据包
- 补充方案:在消息头中标明消息体大小,解析时根据大小读取
面试官追问:如果消息体中也出现了分隔符符号怎么办?
面试者回答:需要在应用层面做特殊处理,因为TCP协议无法处理这种情况。
评价:对粘包概念理解正确,解决方案回答完整。但可以更详细说明如何处理消息体中包含分隔符的情况(如转义处理)。
三、Linux系统
- Linux使用经验 面试官问题:平时使用Linux系统在哪些环境下?
面试者回答:
- 实习公司:通过Windows上的VS Code远程连接Linux服务器开发
- 个人开发:在物理Linux机器上安装运维框架,通过局域网远程开发
评价:回答清晰,展示了实际使用经验。
- Linux命令 面试官问题:如何查找进程ID?如何查看机器上开放的TCP/UDP端口?
面试者回答:
- 查找进程ID:使用top命令结合grep
- 查看端口:使用lsof -a :端口号(应为
ss -a :端口号
或netstat -a :端口号
)
面试官纠正:可以使用netstat或ss命令扫描所有端口,不需要提前知道具体端口号。
评价:对基本命令有一定了解,但命令使用不够准确。sof
应为ss
(socket statistics)命令。
- 文本处理 面试官问题:如何将文件中所有大写字母A替换为小写字母a?
面试者回答:编写shell脚本,读取文件每行,放入字符数组,逐个替换A为a,再写回文件。
面试官建议:可以使用sed或awk等命令行工具更高效处理,如sed 's/A/a/g' file
。
评价:提供了一种解决方案,但不够简洁高效。对Linux文本处理工具了解不足。
四、面试者提问
- 业务方向 面试者问题:如果入职,可能会负责哪一块业务?
面试官回答:主要负责网络通信方面的技术,特别是代理技术(如HTTP代理、SOCKS5代理)相关的服务开发。
- 转正机会 面试者问题:实习岗位转正机会大概是多少?
面试官回答:大部分实习生在毕业时都能转正,只要正常毕业基本都能转正。