面试题答案
一键面试Go语言数组和切片在并发编程中的特性
- 数组特性:
- 固定长度:声明后长度不可变。例如
var arr [5]int
,该数组长度永远是5。 - 值类型:数组作为参数传递时,传递的是整个数组的副本,而不是引用。
- 固定长度:声明后长度不可变。例如
- 切片特性:
- 动态长度:可根据需要动态增长和收缩。例如
slice := make([]int, 0, 10)
,初始长度为0,容量为10,后续可通过append
函数增加元素。 - 引用类型:切片作为参数传递时,传递的是切片的引用,对切片的修改会影响到原始切片。
- 动态长度:可根据需要动态增长和收缩。例如
如何选择使用数组还是切片
- 数组:当数据量固定且不需要动态变化时,可使用数组。例如,一个表示星期几的数组,一周永远是7天,不会变化。
- 切片:在大多数情况下,尤其是数据量不确定或需要动态变化时,应使用切片。例如,在网络编程中接收数据,数据量是不确定的,使用切片更合适。
避免并发操作数组或切片时的数据竞争问题示例
- 使用互斥锁(Mutex):
package main
import (
"fmt"
"sync"
)
var (
mu sync.Mutex
slice = make([]int, 0)
)
func main() {
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func(n int) {
defer wg.Done()
mu.Lock()
slice = append(slice, n)
mu.Unlock()
}(i)
}
wg.Wait()
fmt.Println(slice)
}
- 使用通道(Channel):
package main
import (
"fmt"
)
func main() {
ch := make(chan int)
var result []int
go func() {
for i := 0; i < 10; i++ {
ch <- i
}
close(ch)
}()
for num := range ch {
result = append(result, num)
}
fmt.Println(result)
}
在第一个示例中,通过sync.Mutex
来保护对切片的并发访问,避免数据竞争。在第二个示例中,使用通道来安全地在并发环境中传递数据,从而避免对共享切片的直接并发访问导致的数据竞争。