面试题答案
一键面试设计思路
- 定义命名类型:创建一个结构体来表示共享数据,将相关的数据和操作封装在一起,增强代码的可读性和维护性。
- 使用互斥锁:在命名类型的结构体中嵌入一个
sync.Mutex
来保护共享数据,防止多个goroutine
同时访问造成数据竞争。 - 通道通信:利用通道来安全地在
goroutine
之间传递数据。通过通道发送和接收数据,避免直接对共享数据进行并发读写。
核心代码片段
package main
import (
"fmt"
"sync"
)
// 定义命名类型来管理共享数据
type SharedData struct {
mu sync.Mutex
value int
}
// 定义一个函数来修改共享数据
func (sd *SharedData) updateValue(newValue int, wg *sync.WaitGroup) {
defer wg.Done()
sd.mu.Lock()
sd.value = newValue
sd.mu.Unlock()
}
func main() {
var wg sync.WaitGroup
sharedData := SharedData{}
// 创建通道
dataCh := make(chan int)
// 启动多个goroutine
for i := 0; i < 5; i++ {
wg.Add(1)
go func(num int) {
defer wg.Done()
// 通过通道获取数据
data := <-dataCh
sharedData.updateValue(data, &wg)
}(i)
}
// 向通道发送数据
for i := 0; i < 5; i++ {
dataCh <- i
}
close(dataCh)
wg.Wait()
fmt.Println("Final value:", sharedData.value)
}
在上述代码中:
SharedData
结构体封装了共享数据value
以及一个sync.Mutex
来保护数据。updateValue
方法负责修改共享数据,在修改前加锁,修改后解锁。- 在
main
函数中,创建了一个通道dataCh
用于在goroutine
之间传递数据,启动多个goroutine
从通道接收数据并更新共享数据。通过sync.WaitGroup
来等待所有goroutine
完成操作。