面试题答案
一键面试可能出现的问题
- 竞争条件:多个协程同时进行类型转换操作,可能导致共享数据在转换过程中被其他协程修改,从而引发数据不一致。例如,一个协程正在将
[]byte
转换为自定义结构体,另一个协程却同时修改了这个[]byte
数据。 - 数据不一致:由于类型转换涉及不同的数据结构,不同协程转换的进度不同,可能导致部分协程获取到的数据处于不一致的中间状态。比如,某个协程在自定义结构体尚未完全转换为
map[string]interface{}
时就使用了该数据。
解决方案
- 互斥锁(Mutex):使用
sync.Mutex
来保护共享数据,在进行类型转换操作前后加锁和解锁,确保同一时间只有一个协程能进行转换操作。 - 通道(Channel):通过通道来传递共享数据,使得协程间按顺序进行类型转换,避免同时操作。例如,先将
[]byte
数据发送到一个通道,接收方协程在接收到数据后进行转换,再将转换后的数据发送到下一个通道供后续处理。
示例代码
package main
import (
"fmt"
"sync"
)
// 自定义结构体
type MyStruct struct {
Field1 string
Field2 int
}
func main() {
var wg sync.WaitGroup
var mu sync.Mutex
sharedData := []byte(`{"Field1":"value1","Field2":123}`)
// 用于传递转换后的数据
dataCh := make(chan interface{})
// 模拟多个协程
for i := 0; i < 2; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
mu.Lock()
// 从 []byte 转换为自定义结构体
var myStruct MyStruct
// 这里省略实际的反序列化逻辑,假设这里是正确转换
myStruct.Field1 = "value1"
myStruct.Field2 = 123
// 从自定义结构体转换为 map[string]interface{}
resultMap := make(map[string]interface{})
resultMap["Field1"] = myStruct.Field1
resultMap["Field2"] = myStruct.Field2
mu.Unlock()
dataCh <- resultMap
}(i)
}
go func() {
wg.Wait()
close(dataCh)
}()
// 接收并处理转换后的数据
for data := range dataCh {
fmt.Printf("Received data: %v\n", data)
}
}
在上述代码中:
- 使用
sync.Mutex
来保护共享数据sharedData
的类型转换过程。 - 通过
sync.WaitGroup
来等待所有协程完成类型转换。 - 使用通道
dataCh
来传递转换后的数据,确保主协程能安全地接收并处理这些数据。