网络I/O场景优化
- 并发处理:利用goroutine实现并发的网络I/O操作。例如,对于一个需要从多个网络接口获取数据并进行多值返回的函数,可创建多个goroutine同时进行数据获取。
func fetchDataFromNetwork(urls []string) (map[string]string, error) {
resultChan := make(chan map[string]string, len(urls))
errChan := make(chan error, len(urls))
for _, url := range urls {
go func(u string) {
var data map[string]string
var err error
// 模拟网络请求获取数据
data, err = httpGet(u)
if err != nil {
errChan <- err
} else {
resultChan <- data
}
}(url)
}
results := make(map[string]string)
for i := 0; i < len(urls); i++ {
select {
case result := <-resultChan:
for k, v := range result {
results[k] = v
}
case err := <-errChan:
return nil, err
}
}
close(resultChan)
close(errChan)
return results, nil
}
- Buffered Channels:在使用channel传递多值返回结果时,使用带缓冲的channel。这样可以减少goroutine之间的阻塞,提高并发性能。如上述代码中
resultChan
和errChan
都使用了带缓冲的channel。
CPU密集型场景优化
- Work - Pool模式:对于CPU密集型的多值返回函数,可采用工作池模式。创建一定数量的goroutine作为工作者,将任务分发给它们。例如,计算一个大数组的多个统计值(多值返回)。
type Task struct {
data []int
resultChan chan []int
}
func worker(taskChan chan Task) {
for task := range taskChan {
var sum, max, min int
// 初始化sum, max, min
sum = 0
max = task.data[0]
min = task.data[0]
for _, num := range task.data {
sum += num
if num > max {
max = num
}
if num < min {
min = num
}
}
task.resultChan <- []int{sum, max, min}
}
}
func calculateLargeData(data []int) (int, int, int, error) {
const numWorkers = 4
taskChan := make(chan Task, numWorkers)
resultChan := make(chan []int, numWorkers)
for i := 0; i < numWorkers; i++ {
go worker(taskChan)
}
partSize := (len(data) + numWorkers - 1) / numWorkers
for i := 0; i < numWorkers; i++ {
start := i * partSize
end := (i + 1) * partSize
if end > len(data) {
end = len(data)
}
task := Task{data[start:end], resultChan}
taskChan <- task
}
close(taskChan)
var totalSum, totalMax, totalMin int
for i := 0; i < numWorkers; i++ {
result := <-resultChan
sum, max, min := result[0], result[1], result[2]
totalSum += sum
if max > totalMax {
totalMax = max
}
if min < totalMin {
totalMin = min
}
}
close(resultChan)
return totalSum, totalMax, totalMin, nil
}
- 避免不必要的复制:在CPU密集型操作中,多值返回时尽量避免不必要的数据复制。例如,如果返回大的结构体,可以考虑返回指针,减少内存分配和复制开销。
type BigStruct struct {
data [1000000]int
}
func cpuIntensiveOperation() *BigStruct {
var bs BigStruct
// 进行CPU密集型计算填充bs
return &bs
}