面试题答案
一键面试可能出现的边界问题
- 数据竞争:在高并发环境下,多个 goroutine 同时通过反射修改基础类型数据,如
int
,会导致数据竞争。因为反射操作本身并非原子性的,多个 goroutine 同时读写会造成数据不一致。 - 性能问题:反射操作相对直接操作来说性能较低。频繁使用反射会增加 CPU 开销,在高并发场景下可能成为性能瓶颈。
设计思路
- 使用
sync.Mutex
解决数据竞争:通过互斥锁来保护对基础类型数据的反射操作,确保同一时间只有一个 goroutine 可以进行修改。 - 性能优化:
- 减少反射操作的频率,例如批量处理反射操作而不是每次单个操作。
- 提前缓存反射相关的元信息,如
reflect.Type
和reflect.Value
,避免每次都重新获取。
关键代码片段
package main
import (
"fmt"
"reflect"
"sync"
)
type Data struct {
num int
mu sync.Mutex
}
func (d *Data) SetNumByReflect(newVal int) {
d.mu.Lock()
defer d.mu.Unlock()
valueOf := reflect.ValueOf(d).Elem()
field := valueOf.FieldByName("num")
if field.IsValid() && field.Kind() == reflect.Int {
field.SetInt(int64(newVal))
}
}
func main() {
var wg sync.WaitGroup
data := Data{}
for i := 0; i < 10; i++ {
wg.Add(1)
go func(val int) {
defer wg.Done()
data.SetNumByReflect(val)
}(i)
}
wg.Wait()
fmt.Println("Final value:", data.num)
}
在上述代码中:
Data
结构体包含一个int
类型的字段num
和一个sync.Mutex
类型的字段mu
。SetNumByReflect
方法通过mu
互斥锁保护对num
字段的反射修改操作,避免数据竞争。- 在
main
函数中,启动多个 goroutine 并发调用SetNumByReflect
方法,演示了在高并发场景下如何安全地使用反射修改基础类型数据。