range 关键字详解
基本用法
range
用于迭代各种集合类型:
// 1. 切片迭代 |
特殊用法和技巧
// 忽略索引/键 |
适用场景
- 数据处理:遍历切片、数组处理数据集合
- 映射操作:处理键值对数据(如配置、缓存)
- 字符串处理:正确处理 Unicode 字符
- 通道消费:从通道持续接收数据直到关闭
- 文件处理:结合
bufio.Scanner
逐行读取文件
// 文件逐行读取示例 |
select 关键字详解
基本用法
select
用于处理多个通道操作:
ch1 := make(chan string) |
运行结果为
从ch1接收: hello |
高级用法
// 1. 非阻塞操作 |
适用场景
- 多路复用:同时处理多个通道操作
- 超时控制:使用
time.After
实现操作超时 - 非阻塞操作:使用
default
避免阻塞 - 优雅退出:实现服务优雅关闭机制
- 任务调度:结合定时器实现周期性任务
- 优先级处理:实现通道操作的优先级
range 和 select 的联合应用
通道扇入模式(Fan-In)
func merge(chs ...<-chan int) <-chan int { |
有限并发处理
func processTasks(tasks []Task, concurrency int) { |
带超时的并行请求
func fetchWithTimeout(urls []string, timeout time.Duration) []string { |
性能优化与陷阱避免
range 的性能考虑
// 避免在循环内创建新切片 |
select 的常见陷阱
// 陷阱1: 无法退出的select |
实际应用场景案例
Web 服务器连接管理
type Server struct { |
实时数据处理管道
func dataProcessingPipeline(input <-chan Data) <-chan Result { |
服务优雅关闭
func runServer() error { |
总结与最佳实践
range 最佳实践:
- 使用
for range
替代传统for
循环处理集合 - 在迭代大集合时使用索引而非值拷贝
- 通道迭代必须确保通道最终被关闭
- 使用
_
忽略不需要的返回值 - 修改集合元素时使用索引访问
select 最佳实践:
- 总是包含超时或退出机制
- 使用
default
实现非阻塞操作 - 避免在
select
中执行耗时操作 - 多个
case
就绪时随机执行的设计要牢记 - 结合
context
实现优雅退出
联合使用建议:
- 使用
range
消费select
生成的通道 - 在并发模式中使用
select
管理多个range
循环 - 实现管道模式时组合使用两种机制
- 使用
sync.WaitGroup
管理并发任务的生命周期