面试题答案
一键面试可能出现的问题
在高并发场景下,多个goroutine同时对 interface{}
类型的共享变量进行类型断言和类型转换操作,可能会出现数据竞争问题。因为不同的goroutine可能在同一时间对该变量进行读写操作,导致程序出现未定义行为,例如读到脏数据或者类型断言失败等情况。
设计思路
为了避免数据竞争和确保类型断言与转换的正确性,可以使用sync.Mutex
来保护共享变量。sync.Mutex
是一种互斥锁,通过在对共享变量进行读写操作前加锁,操作完成后解锁,保证同一时间只有一个goroutine可以访问共享变量,从而避免数据竞争。
代码示例
package main
import (
"fmt"
"sync"
)
var (
sharedVar interface{}
mu sync.Mutex
)
func main() {
var wg sync.WaitGroup
// 启动多个goroutine
for i := 0; i < 5; i++ {
wg.Add(1)
go func() {
defer wg.Done()
// 设置共享变量
mu.Lock()
sharedVar = "hello"
mu.Unlock()
// 获取共享变量并进行类型断言和转换
mu.Lock()
if str, ok := sharedVar.(string); ok {
fmt.Println("类型断言成功:", str)
} else {
fmt.Println("类型断言失败")
}
mu.Unlock()
}()
}
wg.Wait()
}
代码解释
-
定义共享变量和互斥锁:
var ( sharedVar interface{} mu sync.Mutex )
定义了一个
interface{}
类型的共享变量sharedVar
和一个互斥锁mu
。 -
启动多个goroutine:
for i := 0; i < 5; i++ { wg.Add(1) go func() { defer wg.Done() // ... }() }
使用
go
关键字启动了5个goroutine,并使用sync.WaitGroup
来等待所有goroutine完成。 -
设置共享变量:
mu.Lock() sharedVar = "hello" mu.Unlock()
在设置共享变量前,通过
mu.Lock()
加锁,操作完成后通过mu.Unlock()
解锁,确保同一时间只有一个goroutine可以设置共享变量。 -
获取共享变量并进行类型断言和转换:
mu.Lock() if str, ok := sharedVar.(string); ok { fmt.Println("类型断言成功:", str) } else { fmt.Println("类型断言失败") } mu.Unlock()
在获取共享变量并进行类型断言和转换前,同样通过
mu.Lock()
加锁,操作完成后通过mu.Unlock()
解锁,确保同一时间只有一个goroutine可以读取和操作共享变量,从而避免数据竞争,保证类型断言和转换的正确性。