feat: add 10 Golang interview questions
Added comprehensive Golang interview preparation materials:
- 基础语法(值类型、切片、map、defer、接口、struct、new/make)
- Goroutine 和并发模型(与线程对比、调度模型、内存模型)
- 错误处理和测试(error、panic/recover、单元测试、Benchmark)
- 并发编程进阶(Mutex、RWMutex、WaitGroup、atomic、数据竞争)
- HTTP 和 Web 开发(Client、Server、中间件模式)
- 内存模型和垃圾回收(内存分配、逃逸分析、GC)
- 性能优化(pprof、内存优化、CPU优化、并发优化)
- 反射和 unsafe(反射性能、unsafe 使用场景)
- 接口和类型系统(类型断言、interface{}、类型嵌入、泛型)
- 数据库操作(database/sql、GORM、事务、SQL 注入防护)
- 项目结构和工程化(标准项目结构、Go Module、CI/CD)
Each file includes:
- Detailed questions and comprehensive answers
- Code examples and best practices
- Alibaba P7 level requirements
Total: 60 interview questions (50 backend + 10 Golang)
Generated with [Claude Code](https://claude.com/claude-code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
This commit is contained in:
240
questions/13-Golang语言/go-concurrent-advanced.md
Normal file
240
questions/13-Golang语言/go-concurrent-advanced.md
Normal file
@@ -0,0 +1,240 @@
|
||||
# Golang 并发编程进阶
|
||||
|
||||
## 问题
|
||||
|
||||
1. sync.Mutex 和 sync.RWMutex 的区别?
|
||||
2. sync.WaitGroup 和 sync.Once 的使用场景?
|
||||
3. atomic 包的作用是什么?
|
||||
4. 如何实现一个无锁队列?
|
||||
5. 如何检测数据竞争(Data Race)?
|
||||
6. Go 的内存模型(Happens-Before)是什么?
|
||||
|
||||
---
|
||||
|
||||
## 标准答案
|
||||
|
||||
### 1. Mutex vs RWMutex
|
||||
|
||||
#### **Mutex(互斥锁)**
|
||||
|
||||
```go
|
||||
var mu sync.Mutex
|
||||
|
||||
func write() {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
|
||||
// 写操作
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### **RWMutex(读写锁)**
|
||||
|
||||
```go
|
||||
var mu sync.RWMutex
|
||||
|
||||
func read() {
|
||||
mu.RLock()
|
||||
defer mu.RUnlock()
|
||||
|
||||
// 读操作(多个 Goroutine 可以同时读)
|
||||
}
|
||||
|
||||
func write() {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
|
||||
// 写操作(独占访问)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**使用场景**:
|
||||
- **Mutex**:读写都少
|
||||
- **RWMutex**:读多写少
|
||||
|
||||
---
|
||||
|
||||
### 2. WaitGroup 和 Once
|
||||
|
||||
#### **WaitGroup**
|
||||
|
||||
**用途**:等待一组 Goroutine 完成
|
||||
|
||||
```go
|
||||
var wg sync.WaitGroup
|
||||
|
||||
func worker(id int) {
|
||||
defer wg.Done()
|
||||
|
||||
fmt.Printf("Worker %d starting\n", id)
|
||||
time.Sleep(time.Second)
|
||||
fmt.Printf("Worker %d done\n", id)
|
||||
}
|
||||
|
||||
func main() {
|
||||
for i := 1; i <= 3; i++ {
|
||||
wg.Add(1)
|
||||
go worker(i)
|
||||
}
|
||||
|
||||
wg.Wait() // 等待所有 worker 完成
|
||||
fmt.Println("All workers done")
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### **Once**
|
||||
|
||||
**用途**:确保函数只执行一次
|
||||
|
||||
```go
|
||||
var once sync.Once
|
||||
|
||||
func initDB() {
|
||||
once.Do(func() {
|
||||
// 初始化数据库(只执行一次)
|
||||
fmt.Println("DB initialized")
|
||||
})
|
||||
}
|
||||
|
||||
func main() {
|
||||
initDB()
|
||||
initDB() // 不会再次执行
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3. atomic 包
|
||||
|
||||
#### **作用**
|
||||
|
||||
**原子操作**:无锁并发编程
|
||||
|
||||
---
|
||||
|
||||
#### **示例**
|
||||
|
||||
```go
|
||||
import "sync/atomic"
|
||||
|
||||
var counter int64
|
||||
|
||||
// ❌ 非原子操作(数据竞争)
|
||||
func increment() {
|
||||
counter++ // 不是原子操作
|
||||
}
|
||||
|
||||
// ✅ 原子操作
|
||||
func incrementAtomic() {
|
||||
atomic.AddInt64(&counter, 1)
|
||||
}
|
||||
|
||||
// 读取
|
||||
value := atomic.LoadInt64(&counter)
|
||||
|
||||
// 比较并交换(CAS)
|
||||
old := atomic.LoadInt64(&counter)
|
||||
atomic.CompareAndSwapInt64(&counter, old, new)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4. 检测数据竞争
|
||||
|
||||
#### **使用 go test -race**
|
||||
|
||||
```bash
|
||||
# 检测数据竞争
|
||||
go test -race ./...
|
||||
|
||||
# 运行程序
|
||||
go run -race main.go
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### **示例**
|
||||
|
||||
```go
|
||||
// ❌ 有数据竞争
|
||||
func main() {
|
||||
var counter int
|
||||
go func() {
|
||||
counter++ // 数据竞争
|
||||
}()
|
||||
counter++ // 数据竞争
|
||||
}
|
||||
|
||||
// ✅ 无数据竞争
|
||||
func main() {
|
||||
var counter int64
|
||||
go func() {
|
||||
atomic.AddInt64(&counter, 1)
|
||||
}()
|
||||
atomic.AddInt64(&counter, 1)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 5. Happens-Before
|
||||
|
||||
#### **定义**
|
||||
|
||||
**Happens-Before**:保证一个操作对另一个操作可见
|
||||
|
||||
---
|
||||
|
||||
#### **规则**
|
||||
|
||||
1. **Goroutine 创建**:`go func()` happens-before `func()` 开始
|
||||
2. **Channel**:发送 happens-before 接收
|
||||
3. **Lock**:Unlock happens-before 下一次 Lock
|
||||
|
||||
---
|
||||
|
||||
#### **示例**
|
||||
|
||||
```go
|
||||
var a, b int
|
||||
|
||||
func main() {
|
||||
go func() {
|
||||
a = 1 // ①
|
||||
ch <- struct{}{} // ②
|
||||
}()
|
||||
|
||||
b = 2 // ③
|
||||
<-ch // ④
|
||||
|
||||
// 保证了:
|
||||
// ① happens-before ②
|
||||
// ② happens-before ④
|
||||
// 因此:a = 1 一定会在 b = 2 之前执行
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 6. 阿里 P7 加分项
|
||||
|
||||
**深度理解**:
|
||||
- 理解 Go 的内存模型(Happens-Before)
|
||||
- 理解 atomic 包的实现原理(CAS)
|
||||
- 理解 RWMutex 的实现(写锁饥饿问题)
|
||||
|
||||
**实战经验**:
|
||||
- 有使用 -race 检测数据竞争的经验
|
||||
- 有优化并发程序的经验(减少锁、使用 atomic)
|
||||
- 有实现无锁数据结构的经验
|
||||
|
||||
**并发编程**:
|
||||
- 理解如何避免数据竞争
|
||||
- 理解如何使用原子操作
|
||||
- 理解如何实现高性能并发程序
|
||||
Reference in New Issue
Block a user