🧱 基础篇(语法、类型、函数)
-
Golang有哪些优势? — 并发、编译快、跨平台等核心特性介绍
-
Golang数据类型有哪些 — 整型、浮点型、布尔、字符串等基本数据类型
-
Golang中的包如何使用 — 包的导入、路径结构和作用域
-
Go支持什么形式的类型转换? — 显式转换、接口断言、类型推断等
-
Go语言当中interface的实现原理 — 接口底层结构 itab、动态派发机制
-
如何在运行时检查变量类型? — 使用 type switch 和 type assertion
-
Go两个接口之间可以存在什么关系? — 接口嵌套组合、空接口、多态实现
-
Golang中int和int64区别 — int 是平台相关的;int64 是固定长度
-
Golang中的指针可以进行运算吗? — 不支持指针算术,与 C 不同
-
Golang中函数返回多个值的原理 — 多返回值通过结构体方式实现
-
Go语言是值传递还是引用传递? — 全部是值传递,引用类型值传的是地址
-
Go语言中的常量和枚举定义方式 — 使用 const 和 iota 构造枚举
-
Go语言当中new的作用是什么? — 分配内存并返回类型指针
-
Go语言中make的作用是什么? — 创建 slice、map、channel 等引用类型
-
Printf(), Sprintf(), Fprintf()有什么不同? — 分别输出到控制台、字符串、文件
-
Go语言当中数组和切片的区别是什么? — 数组是固定长度,切片是动态可变引用类型
-
数组和切片底层实现是一样的吗? — 切片是数组的一个视图 + 元信息
-
切片的三种初始化方式是什么? — 字面量、make、从数组或切片截取
-
Go语言是如何实现切片扩容的? — 每次扩容成倍增加(小切片翻倍,大切片按1.25倍)
-
切片中cap和len的区别是什么? — len 是长度,cap 是容量,影响扩容行为
-
Golang Slice 的底层实现 — Slice 本质是结构体,包含指针、len、cap
-
Go中map的并发安全问题 — 原生 map 非线程安全,需要加锁或使用 sync.Map
-
Go语言中的map是如何实现的? — hashmap 实现,使用 open addressing + overflow buckets
-
Go语言的字符串是如何实现的? — string 是不可变类型,底层为字节数组和长度
-
字符串和rune的区别? — string 是 UTF-8 编码字节序列,rune 是 Unicode 编码点
🚦进阶篇(并发、内存管理、异常处理)
-
Golang中的rune底层实现 — rune 是 int32,表示 Unicode 字符,支持多字节字符
-
Go中defer的执行顺序 — defer 按后进先出(LIFO)顺序执行
-
defer和return哪个先执行? — 先计算 return 值 → 再执行 defer → 最后返回
-
Golang中的panic和recover — panic 触发异常,recover 捕捉异常防止程序崩溃
-
如何使用recover捕获panic — 在 defer 中使用 recover() 判断错误类型
-
Go语言中struct和class的区别 — Go 没有 class,struct + 方法 + 接口实现 OOP
-
如何实现Go中的继承 — 通过结构体嵌套实现组合复用
-
Go语言中的组合和继承的区别 — Go 推崇组合优于继承,结构体可匿名组合
-
Go中如何实现多态 — 通过接口实现多态,动态绑定方法
-
Go语言的interface和duck typing — 实现接口无需显式声明,符合“鸭子类型”
-
Go中的Goroutine是线程吗? — Goroutine 是用户态的轻量线程,由 Go 运行时调度
-
Goroutine调度模型 — M:N 模型,G(Goroutine)、M(Thread)、P(Processor)三者协作
-
Go语言的channel实现原理 — channel 是基于 CSP 模型的通信机制,底层为队列
-
如何关闭channel?关闭后还能发送/接收吗? — 关闭后不能发送,只能读取(返回零值和关闭状态)
-
channel有哪些使用场景? — 协程通信、任务同步、资源池控制等
-
select语句是干什么用的? — 监听多个 channel 中的操作,非阻塞选择
-
Go语言的定时器机制是怎么实现的? — 使用
time.NewTimer()
和time.After()
-
Go语言中timer和ticker的区别 — timer 一次触发,ticker 周期性触发
-
Go语言中sync包的作用 — 提供互斥锁、读写锁、等待组、Once 等原语
-
Go中sync.Mutex的使用 — 互斥锁保护临界区,避免数据竞争
-
sync.WaitGroup使用场景 — 等待多个 Goroutine 结束再继续执行
-
Go语言中的死锁是如何产生的? — 多个协程互相等待对方释放资源
-
Go中如何检测数据竞争? — 使用
-race
标志运行程序检测并发访问冲突 -
Go语言中的内存逃逸分析是什么? — 判断变量分配在栈上还是堆上
-
如何查看Go代码是否发生了逃逸? — 使用
go build -gcflags="-m"
查看编译器逃逸信息
📦进阶篇(内存管理、调度、网络、工具)
-
Go中map是线程安全的吗? — 默认 map 不是线程安全的,需加锁或使用 sync.Map
-
sync.Map和普通map的区别? — sync.Map 并发安全,使用读写分离机制和懒惰删除
-
Go语言中的slice扩容机制 — 容量小于 1024 时翻倍扩容,大于则按 1.25 倍增长
-
Go中make和new的区别 — make 初始化内建引用类型,new 分配零值指针
-
Go中struct是值类型还是引用类型? — struct 是值类型,赋值会拷贝全部字段
-
Go中的深拷贝和浅拷贝 — 浅拷贝复制引用,深拷贝复制底层数据
-
Go语言的垃圾回收机制 — 使用三色标记算法,支持并发、增量、STW
-
Go语言中的逃逸分析原理 — 编译器分析变量是否逃出函数栈帧范围
-
Golang中的内存对齐 — 为提升 CPU 读取效率,结构体按字段大小对齐
-
Go的内存泄漏场景有哪些? — 协程未退出、channel未关闭、全局引用未释放等
-
Go中的反射机制 — 使用
reflect
包运行时查看和操作类型信息 -
Go反射的使用场景? — 通用框架、JSON解析、ORM、依赖注入等
-
Go中如何获取变量类型? — 使用
reflect.TypeOf()
获取类型,Kind()
获取分类 -
Go语言中的空接口interface{} — 万能类型,可接受任意值,实现了所有接口
-
Go中类型断言的原理 — 类型断言从空接口恢复原始类型,失败会 panic
-
Go语言中的net包 — 提供 TCP/UDP/Unix 网络通信接口
-
Go语言中的http包 — 内置 HTTP 服务端和客户端库,简洁高效
-
如何实现一个HTTP服务器 — 使用
http.ListenAndServe()
+ handler 函数 -
Go语言中的context的作用 — 控制 goroutine 生命周期、传递元数据、取消信号
-
context.WithCancel、WithTimeout、WithValue区别 — 分别用于取消控制、超时控制、值传递
-
Go语言如何做性能分析 — 使用
pprof
包,分析 CPU、内存、阻塞等 -
Go中的race检测原理 — 插桩记录变量访问,检测冲突
-
Go如何编写单元测试 —
testing
包 +_test.go
文件 +TestXXX
函数 -
Go中的测试覆盖率如何查看? — 使用
go test -cover
输出覆盖率 -
Go语言如何做Mock测试? — 手写 mock 或使用 gomock/mockery 等工具生成
📦进阶篇(部署、项目经验、最佳实践)
-
Go中panic和recover机制详解 — panic 会中断流程,recover 捕获 panic 恢复程序
-
Go中的defer执行顺序是怎样的? — 后进先出(LIFO),即最后定义的 defer 最先执行
-
defer中修改返回值的技巧 — 需使用命名返回值,在 defer 中直接修改
-
Go如何优雅关闭服务? — 使用
context
+os.Signal
捕获中断信号,执行清理逻辑 -
Go的日志打印方案有哪些? — 标准库 log、zap、logrus、zerolog 等
-
Go的错误处理方式 — 标准
error
接口、自定义错误类型、errors.Wrap 等 -
Go语言中常见的错误处理模式 — if err != nil、包装错误、类型断言处理
-
Go项目目录结构推荐 — 分为
cmd/
,pkg/
,internal/
,api/
,configs/
等模块 -
Go语言如何跨平台编译? — 设置
GOOS
和GOARCH
变量后执行go build
-
Go模块化管理(Go Modules)详解 — 使用 go.mod/go.sum 管理依赖,解决 GOPATH 局限
-
Go语言如何优雅处理第三方依赖? — 使用
go mod tidy
、语义版本、vendor 模式 -
Go中init函数的执行顺序 — 按包依赖顺序,先变量初始化,后执行 init()
-
Go语言中main包只能有一个吗? — 是的,main 包作为程序入口只能存在一个 main 函数
-
如何使用go build构建生产可执行文件? —
go build -ldflags "-s -w"
精简体积 +strip
压缩 -
如何使用go run快速测试代码? —
go run main.go
编译并立即运行,适合临时验证 -
Go语言中如何进行配置管理? — 配置文件(JSON/YAML)、环境变量、flag 参数
-
Go项目如何加载和使用配置? — 使用 viper、envconfig 等库统一读取管理配置
-
Go项目中常用的Web框架有哪些? — Gin、Echo、Fiber、Beego、Revel 等
-
Gin框架的中间件机制原理 — 本质是链式函数调用(洋葱模型)
-
Go中如何使用中间件做权限校验? — 在 handler 前统一校验 JWT、Session、Token
-
如何在Go中实现RESTful API? — 使用路由区分 GET/POST/PUT/DELETE,对应资源操作
-
Go项目中使用JWT的最佳实践 — 签名密钥安全、过期策略、刷新机制、权限载荷
-
Go如何做权限设计? — RBAC 模型(角色权限控制),结合中间件处理鉴权
-
Go如何进行API版本管理? — 使用路径或子路由区分,如 /v1/, /v2/ 等
-
Go项目部署常见方式 — 使用 systemd、Supervisor、Docker、K8s 等工具部署服务