面试题答案
一键面试可能遇到的问题
- 数据竞争:多个 goroutine 同时读写上下文的值,会导致数据竞争问题,使程序出现未定义行为。
- context 不可变特性:context 本身是不可变的,不能直接修改其值。
解决思路
- 使用共享变量并加锁:通过一个共享变量来存储需要修改的值,使用互斥锁(
sync.Mutex
)来保护对该变量的读写操作,确保同一时间只有一个 goroutine 能修改或读取该值。 - 使用 channel 通知:结合 channel 来通知其他 goroutine 值已发生变化,让其他 goroutine 主动从共享变量中获取最新值。
关键代码片段
package main
import (
"context"
"fmt"
"sync"
)
type ContextValue struct {
Value int
}
func main() {
var mu sync.Mutex
var sharedValue ContextValue
valueChanged := make(chan struct{})
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// 模拟修改上下文值的 goroutine
go func() {
for {
select {
case <-ctx.Done():
return
default:
mu.Lock()
sharedValue.Value++
mu.Unlock()
valueChanged <- struct{}{}
}
}
}()
// 模拟获取上下文值的 goroutine
go func() {
for {
select {
case <-ctx.Done():
return
case <-valueChanged:
mu.Lock()
fmt.Println("New value:", sharedValue.Value)
mu.Unlock()
}
}
}()
// 模拟程序运行一段时间
select {}
}
在上述代码中:
ContextValue
结构体用于表示上下文的值。mu
是一个互斥锁,用于保护对sharedValue
的读写操作。valueChanged
是一个 channel,用于通知其他 goroutine 值已发生变化。- 第一个 goroutine 定期修改
sharedValue
,并通过valueChanged
channel 通知其他 goroutine。 - 第二个 goroutine 收到通知后,获取并打印最新的
sharedValue
。