面试题答案
一键面试基本原理
- goroutine:
- 在Go语言中,goroutine是一种轻量级的线程,由Go运行时(runtime)管理。与操作系统线程相比,goroutine的创建和销毁开销非常小,可以轻松创建成千上万的goroutine。
- 当一个函数被作为goroutine启动时,它会与其他goroutine并发执行。例如,
go someFunction()
这样的语句会在新的goroutine中启动someFunction
函数的执行,而不会阻塞当前goroutine的执行。
- channel:
- channel是用于在goroutine之间进行通信和同步的管道。它可以是有缓冲的或无缓冲的。
- 无缓冲的channel要求发送和接收操作同时进行,否则发送或接收操作会阻塞,直到另一方准备好。例如,
ch := make(chan int)
创建一个无缓冲的整数类型channel。 - 有缓冲的channel允许在没有接收方的情况下发送一定数量的数据,缓冲大小在创建时指定,如
ch := make(chan int, 10)
创建一个缓冲大小为10的整数类型channel。 - 通过channel,goroutine之间可以安全地传递数据,避免了共享内存带来的竞态条件问题。
示例代码
package main
import (
"fmt"
)
func sumDivisibleBy3(start, end int, resultChan chan int) {
sum := 0
for i := start; i <= end; i++ {
if i%3 == 0 {
sum += i
}
}
resultChan <- sum
}
func main() {
const numWorkers = 10
const totalRange = 1000000
chunkSize := totalRange / numWorkers
resultChan := make(chan int, numWorkers)
for i := 0; i < numWorkers; i++ {
start := i*chunkSize + 1
end := (i + 1) * chunkSize
if i == numWorkers-1 {
end = totalRange
}
go sumDivisibleBy3(start, end, resultChan)
}
totalSum := 0
for i := 0; i < numWorkers; i++ {
totalSum += <-resultChan
}
close(resultChan)
fmt.Printf("Sum of numbers divisible by 3 from 1 to %d is %d\n", totalRange, totalSum)
}
在上述代码中:
- 任务分配:
- 将1到1000000的范围分成10个部分(
numWorkers
为10),每个部分的大小为chunkSize
。 - 每个goroutine负责计算一个部分内所有能被3整除的数的和。
- 将1到1000000的范围分成10个部分(
- 数据传递和同步:
- 使用一个
resultChan
来接收每个goroutine计算的部分和。 - 主goroutine通过从
resultChan
接收数据,并累加到totalSum
中,从而得到最终的总和。 - 当所有goroutine完成计算并将结果发送到
resultChan
后,主goroutine关闭resultChan
并输出最终结果。
- 使用一个