698 lines
16 KiB
Go
698 lines
16 KiB
Go
/*
|
||
04-range.go - Go 语言 range 关键字详解
|
||
|
||
学习目标:
|
||
1. 掌握 range 的基本用法
|
||
2. 理解 range 在不同数据类型上的应用
|
||
3. 学会处理 range 返回的索引和值
|
||
4. 了解 range 的性能特点
|
||
5. 掌握 range 的实际应用场景
|
||
|
||
知识点:
|
||
- range 遍历数组和切片
|
||
- range 遍历字符串
|
||
- range 遍历映射 (map)
|
||
- range 遍历通道 (channel)
|
||
- range 的值拷贝特性
|
||
- 忽略索引或值的技巧
|
||
- range 的性能考虑
|
||
*/
|
||
|
||
package main
|
||
|
||
import (
|
||
"fmt"
|
||
"unicode/utf8"
|
||
)
|
||
|
||
func main() {
|
||
fmt.Println("=== Go 语言 range 关键字详解 ===\n")
|
||
|
||
// 演示 range 遍历数组和切片
|
||
demonstrateRangeArraySlice()
|
||
|
||
// 演示 range 遍历字符串
|
||
demonstrateRangeString()
|
||
|
||
// 演示 range 遍历映射
|
||
demonstrateRangeMap()
|
||
|
||
// 演示 range 遍历通道
|
||
demonstrateRangeChannel()
|
||
|
||
// 演示 range 的值拷贝特性
|
||
demonstrateRangeValueCopy()
|
||
|
||
// 演示忽略索引或值
|
||
demonstrateIgnoreIndexValue()
|
||
|
||
// 演示 range 的实际应用
|
||
demonstratePracticalExamples()
|
||
|
||
// 演示 range 的性能考虑
|
||
demonstratePerformanceConsiderations()
|
||
}
|
||
|
||
// demonstrateRangeArraySlice 演示 range 遍历数组和切片
|
||
func demonstrateRangeArraySlice() {
|
||
fmt.Println("1. range 遍历数组和切片:")
|
||
|
||
// 遍历数组
|
||
fmt.Printf(" 遍历数组:\n")
|
||
arr := [5]int{10, 20, 30, 40, 50}
|
||
|
||
for index, value := range arr {
|
||
fmt.Printf(" arr[%d] = %d\n", index, value)
|
||
}
|
||
|
||
// 遍历切片
|
||
fmt.Printf(" 遍历切片:\n")
|
||
slice := []string{"Go", "Python", "Java", "JavaScript"}
|
||
|
||
for i, lang := range slice {
|
||
fmt.Printf(" 语言 %d: %s\n", i+1, lang)
|
||
}
|
||
|
||
// 遍历空切片
|
||
fmt.Printf(" 遍历空切片:\n")
|
||
var emptySlice []int
|
||
count := 0
|
||
for range emptySlice {
|
||
count++
|
||
}
|
||
fmt.Printf(" 空切片遍历次数: %d\n", count)
|
||
|
||
// 遍历 nil 切片
|
||
fmt.Printf(" 遍历 nil 切片:\n")
|
||
var nilSlice []int = nil
|
||
count = 0
|
||
for range nilSlice {
|
||
count++
|
||
}
|
||
fmt.Printf(" nil 切片遍历次数: %d\n", count)
|
||
|
||
// 多维切片遍历
|
||
fmt.Printf(" 遍历二维切片:\n")
|
||
matrix := [][]int{
|
||
{1, 2, 3},
|
||
{4, 5, 6},
|
||
{7, 8, 9},
|
||
}
|
||
|
||
for i, row := range matrix {
|
||
for j, value := range row {
|
||
fmt.Printf(" matrix[%d][%d] = %d\n", i, j, value)
|
||
}
|
||
}
|
||
|
||
fmt.Println()
|
||
}
|
||
|
||
// demonstrateRangeString 演示 range 遍历字符串
|
||
func demonstrateRangeString() {
|
||
fmt.Println("2. range 遍历字符串:")
|
||
|
||
// 基本字符串遍历
|
||
fmt.Printf(" 遍历 ASCII 字符串:\n")
|
||
str1 := "Hello"
|
||
|
||
for index, char := range str1 {
|
||
fmt.Printf(" str1[%d] = '%c' (Unicode: %d)\n", index, char, char)
|
||
}
|
||
|
||
// 遍历包含中文的字符串
|
||
fmt.Printf(" 遍历包含中文的字符串:\n")
|
||
str2 := "Hello世界"
|
||
|
||
for index, char := range str2 {
|
||
fmt.Printf(" 位置 %d: '%c' (Unicode: %d)\n", index, char, char)
|
||
}
|
||
|
||
// 注意:index 是字节位置,不是字符位置
|
||
fmt.Printf(" 注意: range 返回的索引是字节位置,不是字符位置\n")
|
||
|
||
// 字符串长度对比
|
||
fmt.Printf(" 字符串长度对比:\n")
|
||
fmt.Printf(" 字节长度 len(\"%s\"): %d\n", str2, len(str2))
|
||
fmt.Printf(" 字符长度 utf8.RuneCountInString(\"%s\"): %d\n",
|
||
str2, utf8.RuneCountInString(str2))
|
||
|
||
// 遍历字符串的字节
|
||
fmt.Printf(" 按字节遍历字符串:\n")
|
||
for i := 0; i < len(str2); i++ {
|
||
fmt.Printf(" 字节 %d: %d ('%c')\n", i, str2[i], str2[i])
|
||
if i >= 7 { // 限制输出
|
||
fmt.Printf(" ...\n")
|
||
break
|
||
}
|
||
}
|
||
|
||
// 统计字符类型
|
||
fmt.Printf(" 统计字符类型:\n")
|
||
text := "Hello, 世界! 123"
|
||
ascii, unicode, digit, other := 0, 0, 0, 0
|
||
|
||
for _, char := range text {
|
||
switch {
|
||
case char >= 'A' && char <= 'Z' || char >= 'a' && char <= 'z':
|
||
ascii++
|
||
case char >= '0' && char <= '9':
|
||
digit++
|
||
case char > 127:
|
||
unicode++
|
||
default:
|
||
other++
|
||
}
|
||
}
|
||
|
||
fmt.Printf(" 文本: \"%s\"\n", text)
|
||
fmt.Printf(" ASCII字母: %d, Unicode字符: %d, 数字: %d, 其他: %d\n",
|
||
ascii, unicode, digit, other)
|
||
|
||
fmt.Println()
|
||
}
|
||
|
||
// demonstrateRangeMap 演示 range 遍历映射
|
||
func demonstrateRangeMap() {
|
||
fmt.Println("3. range 遍历映射 (map):")
|
||
|
||
// 基本映射遍历
|
||
fmt.Printf(" 遍历基本映射:\n")
|
||
scores := map[string]int{
|
||
"Alice": 95,
|
||
"Bob": 87,
|
||
"Charlie": 92,
|
||
"David": 78,
|
||
}
|
||
|
||
for name, score := range scores {
|
||
fmt.Printf(" %s: %d分\n", name, score)
|
||
}
|
||
|
||
// 注意:映射遍历顺序是随机的
|
||
fmt.Printf(" 注意: 映射的遍历顺序是随机的\n")
|
||
|
||
// 遍历复杂映射
|
||
fmt.Printf(" 遍历复杂映射:\n")
|
||
students := map[string]map[string]interface{}{
|
||
"student1": {
|
||
"name": "张三",
|
||
"age": 20,
|
||
"grade": "A",
|
||
},
|
||
"student2": {
|
||
"name": "李四",
|
||
"age": 21,
|
||
"grade": "B",
|
||
},
|
||
}
|
||
|
||
for id, info := range students {
|
||
fmt.Printf(" 学生ID: %s\n", id)
|
||
for key, value := range info {
|
||
fmt.Printf(" %s: %v\n", key, value)
|
||
}
|
||
}
|
||
|
||
// 统计映射信息
|
||
fmt.Printf(" 统计映射信息:\n")
|
||
wordCount := map[string]int{
|
||
"go": 10,
|
||
"python": 8,
|
||
"java": 15,
|
||
"rust": 5,
|
||
}
|
||
|
||
totalWords := 0
|
||
maxCount := 0
|
||
mostPopular := ""
|
||
|
||
for word, count := range wordCount {
|
||
totalWords += count
|
||
if count > maxCount {
|
||
maxCount = count
|
||
mostPopular = word
|
||
}
|
||
}
|
||
|
||
fmt.Printf(" 词汇统计: %v\n", wordCount)
|
||
fmt.Printf(" 总词数: %d\n", totalWords)
|
||
fmt.Printf(" 最受欢迎的词: %s (%d次)\n", mostPopular, maxCount)
|
||
|
||
// 遍历空映射
|
||
fmt.Printf(" 遍历空映射:\n")
|
||
emptyMap := make(map[string]int)
|
||
count := 0
|
||
for range emptyMap {
|
||
count++
|
||
}
|
||
fmt.Printf(" 空映射遍历次数: %d\n", count)
|
||
|
||
fmt.Println()
|
||
}
|
||
|
||
// demonstrateRangeChannel 演示 range 遍历通道
|
||
func demonstrateRangeChannel() {
|
||
fmt.Println("4. range 遍历通道 (channel):")
|
||
|
||
fmt.Printf(" 基本通道遍历:\n")
|
||
|
||
// 创建一个通道并发送数据
|
||
ch := make(chan int, 5)
|
||
|
||
// 发送数据到通道
|
||
for i := 1; i <= 5; i++ {
|
||
ch <- i * 10
|
||
}
|
||
close(ch) // 关闭通道,range 才能正常结束
|
||
|
||
// 使用 range 遍历通道
|
||
for value := range ch {
|
||
fmt.Printf(" 从通道接收: %d\n", value)
|
||
}
|
||
|
||
// 字符串通道示例
|
||
fmt.Printf(" 字符串通道遍历:\n")
|
||
strCh := make(chan string, 3)
|
||
|
||
messages := []string{"Hello", "World", "Go"}
|
||
for _, msg := range messages {
|
||
strCh <- msg
|
||
}
|
||
close(strCh)
|
||
|
||
for message := range strCh {
|
||
fmt.Printf(" 消息: %s\n", message)
|
||
}
|
||
|
||
// 注意:如果通道没有关闭,range 会一直等待
|
||
fmt.Printf(" 注意: 通道必须关闭,否则 range 会一直等待\n")
|
||
|
||
fmt.Println()
|
||
}
|
||
|
||
// demonstrateRangeValueCopy 演示 range 的值拷贝特性
|
||
func demonstrateRangeValueCopy() {
|
||
fmt.Println("5. range 的值拷贝特性:")
|
||
|
||
fmt.Printf(" range 会拷贝值,修改拷贝不会影响原始数据:\n")
|
||
|
||
// 结构体切片示例
|
||
type Person struct {
|
||
Name string
|
||
Age int
|
||
}
|
||
|
||
people := []Person{
|
||
{"Alice", 25},
|
||
{"Bob", 30},
|
||
{"Charlie", 35},
|
||
}
|
||
|
||
fmt.Printf(" 原始数据:\n")
|
||
for i, person := range people {
|
||
fmt.Printf(" people[%d]: %+v\n", i, person)
|
||
}
|
||
|
||
// 尝试修改 range 返回的值(不会影响原始数据)
|
||
fmt.Printf(" 尝试修改 range 返回的值:\n")
|
||
for i, person := range people {
|
||
person.Age += 10 // 这不会修改原始数据
|
||
fmt.Printf(" 修改后的拷贝 people[%d]: %+v\n", i, person)
|
||
}
|
||
|
||
fmt.Printf(" 原始数据(未改变):\n")
|
||
for i, person := range people {
|
||
fmt.Printf(" people[%d]: %+v\n", i, person)
|
||
}
|
||
|
||
// 正确的修改方式:使用索引
|
||
fmt.Printf(" 正确的修改方式(使用索引):\n")
|
||
for i := range people {
|
||
people[i].Age += 5
|
||
}
|
||
|
||
for i, person := range people {
|
||
fmt.Printf(" people[%d]: %+v\n", i, person)
|
||
}
|
||
|
||
// 指针切片的情况
|
||
fmt.Printf(" 指针切片的情况:\n")
|
||
ptrPeople := []*Person{
|
||
{"David", 28},
|
||
{"Eve", 32},
|
||
}
|
||
|
||
// 通过指针修改(会影响原始数据)
|
||
for _, personPtr := range ptrPeople {
|
||
personPtr.Age += 2
|
||
}
|
||
|
||
for i, personPtr := range ptrPeople {
|
||
fmt.Printf(" ptrPeople[%d]: %+v\n", i, *personPtr)
|
||
}
|
||
|
||
fmt.Println()
|
||
}
|
||
|
||
// demonstrateIgnoreIndexValue 演示忽略索引或值
|
||
func demonstrateIgnoreIndexValue() {
|
||
fmt.Println("6. 忽略索引或值:")
|
||
|
||
// 只需要值,忽略索引
|
||
fmt.Printf(" 只需要值,忽略索引(使用 _ ):\n")
|
||
numbers := []int{1, 4, 9, 16, 25}
|
||
sum := 0
|
||
|
||
for _, value := range numbers {
|
||
sum += value
|
||
}
|
||
fmt.Printf(" 数组 %v 的和: %d\n", numbers, sum)
|
||
|
||
// 只需要索引,忽略值
|
||
fmt.Printf(" 只需要索引,忽略值:\n")
|
||
items := []string{"apple", "banana", "cherry", "date"}
|
||
|
||
for index := range items {
|
||
fmt.Printf(" 索引 %d\n", index)
|
||
}
|
||
|
||
// 既不需要索引也不需要值(只是计数)
|
||
fmt.Printf(" 只计算元素个数:\n")
|
||
data := []float64{1.1, 2.2, 3.3, 4.4, 5.5}
|
||
count := 0
|
||
|
||
for range data {
|
||
count++
|
||
}
|
||
fmt.Printf(" 元素个数: %d\n", count)
|
||
|
||
// 映射中忽略键或值
|
||
fmt.Printf(" 映射中忽略键或值:\n")
|
||
grades := map[string]int{
|
||
"Math": 90,
|
||
"English": 85,
|
||
"Science": 92,
|
||
}
|
||
|
||
// 只要值
|
||
fmt.Printf(" 所有分数: ")
|
||
for _, score := range grades {
|
||
fmt.Printf("%d ", score)
|
||
}
|
||
fmt.Printf("\n")
|
||
|
||
// 只要键
|
||
fmt.Printf(" 所有科目: ")
|
||
for subject := range grades {
|
||
fmt.Printf("%s ", subject)
|
||
}
|
||
fmt.Printf("\n")
|
||
|
||
fmt.Println()
|
||
}
|
||
|
||
// demonstratePracticalExamples 演示 range 的实际应用
|
||
func demonstratePracticalExamples() {
|
||
fmt.Println("7. range 的实际应用:")
|
||
|
||
// 示例1: 数据统计
|
||
fmt.Printf(" 示例1 - 销售数据统计:\n")
|
||
sales := map[string][]int{
|
||
"Q1": {100, 120, 110, 130},
|
||
"Q2": {140, 135, 150, 145},
|
||
"Q3": {160, 155, 170, 165},
|
||
"Q4": {180, 175, 190, 185},
|
||
}
|
||
|
||
yearTotal := 0
|
||
for quarter, monthlySales := range sales {
|
||
quarterTotal := 0
|
||
for _, monthSale := range monthlySales {
|
||
quarterTotal += monthSale
|
||
}
|
||
yearTotal += quarterTotal
|
||
fmt.Printf(" %s 季度总销售额: %d\n", quarter, quarterTotal)
|
||
}
|
||
fmt.Printf(" 全年总销售额: %d\n", yearTotal)
|
||
|
||
// 示例2: 配置文件处理
|
||
fmt.Printf(" 示例2 - 配置文件处理:\n")
|
||
config := map[string]interface{}{
|
||
"server_port": 8080,
|
||
"debug_mode": true,
|
||
"database_url": "localhost:5432",
|
||
"max_connections": 100,
|
||
"timeout": 30.5,
|
||
}
|
||
|
||
for key, value := range config {
|
||
fmt.Printf(" 配置项 %s: ", key)
|
||
switch v := value.(type) {
|
||
case int:
|
||
fmt.Printf("%d (整数)\n", v)
|
||
case bool:
|
||
fmt.Printf("%t (布尔值)\n", v)
|
||
case string:
|
||
fmt.Printf("\"%s\" (字符串)\n", v)
|
||
case float64:
|
||
fmt.Printf("%.1f (浮点数)\n", v)
|
||
default:
|
||
fmt.Printf("%v (未知类型)\n", v)
|
||
}
|
||
}
|
||
|
||
// 示例3: 文本处理
|
||
fmt.Printf(" 示例3 - 单词频率统计:\n")
|
||
text := "go is great go is simple go is fast"
|
||
words := []string{"go", "is", "great", "go", "is", "simple", "go", "is", "fast"}
|
||
|
||
wordFreq := make(map[string]int)
|
||
for _, word := range words {
|
||
wordFreq[word]++
|
||
}
|
||
|
||
fmt.Printf(" 文本: \"%s\"\n", text)
|
||
fmt.Printf(" 词频统计:\n")
|
||
for word, freq := range wordFreq {
|
||
fmt.Printf(" \"%s\": %d次\n", word, freq)
|
||
}
|
||
|
||
// 示例4: 数据验证
|
||
fmt.Printf(" 示例4 - 用户数据验证:\n")
|
||
users := []map[string]string{
|
||
{"name": "Alice", "email": "alice@example.com", "age": "25"},
|
||
{"name": "", "email": "bob@test.com", "age": "30"},
|
||
{"name": "Charlie", "email": "invalid-email", "age": "abc"},
|
||
{"name": "David", "email": "david@domain.org", "age": "28"},
|
||
}
|
||
|
||
validUsers := 0
|
||
for i, user := range users {
|
||
fmt.Printf(" 用户 %d: ", i+1)
|
||
isValid := true
|
||
|
||
// 验证姓名
|
||
if user["name"] == "" {
|
||
fmt.Printf("姓名为空 ")
|
||
isValid = false
|
||
}
|
||
|
||
// 验证邮箱(简单验证)
|
||
email := user["email"]
|
||
if !contains(email, "@") || !contains(email, ".") {
|
||
fmt.Printf("邮箱无效 ")
|
||
isValid = false
|
||
}
|
||
|
||
// 验证年龄
|
||
age := user["age"]
|
||
if !isNumeric(age) {
|
||
fmt.Printf("年龄无效 ")
|
||
isValid = false
|
||
}
|
||
|
||
if isValid {
|
||
fmt.Printf("✓ 有效用户\n")
|
||
validUsers++
|
||
} else {
|
||
fmt.Printf("✗ 无效用户\n")
|
||
}
|
||
}
|
||
|
||
fmt.Printf(" 有效用户数: %d/%d\n", validUsers, len(users))
|
||
|
||
// 示例5: 矩阵操作
|
||
fmt.Printf(" 示例5 - 矩阵转置:\n")
|
||
matrix := [][]int{
|
||
{1, 2, 3},
|
||
{4, 5, 6},
|
||
}
|
||
|
||
fmt.Printf(" 原矩阵:\n")
|
||
for i, row := range matrix {
|
||
fmt.Printf(" 行 %d: %v\n", i, row)
|
||
}
|
||
|
||
// 创建转置矩阵
|
||
if len(matrix) > 0 {
|
||
transposed := make([][]int, len(matrix[0]))
|
||
for i := range transposed {
|
||
transposed[i] = make([]int, len(matrix))
|
||
}
|
||
|
||
for i, row := range matrix {
|
||
for j, value := range row {
|
||
transposed[j][i] = value
|
||
}
|
||
}
|
||
|
||
fmt.Printf(" 转置矩阵:\n")
|
||
for i, row := range transposed {
|
||
fmt.Printf(" 行 %d: %v\n", i, row)
|
||
}
|
||
}
|
||
|
||
fmt.Println()
|
||
}
|
||
|
||
// demonstratePerformanceConsiderations 演示 range 的性能考虑
|
||
func demonstratePerformanceConsiderations() {
|
||
fmt.Println("8. range 的性能考虑:")
|
||
|
||
// 大切片的遍历
|
||
fmt.Printf(" 大切片的遍历性能:\n")
|
||
largeSlice := make([]int, 1000)
|
||
for i := range largeSlice {
|
||
largeSlice[i] = i
|
||
}
|
||
|
||
// 使用 range(推荐)
|
||
sum1 := 0
|
||
for _, value := range largeSlice {
|
||
sum1 += value
|
||
if sum1 > 100 { // 提前退出演示
|
||
break
|
||
}
|
||
}
|
||
fmt.Printf(" 使用 range 遍历(推荐): 部分和 = %d\n", sum1)
|
||
|
||
// 使用传统 for 循环
|
||
sum2 := 0
|
||
for i := 0; i < len(largeSlice); i++ {
|
||
sum2 += largeSlice[i]
|
||
if sum2 > 100 {
|
||
break
|
||
}
|
||
}
|
||
fmt.Printf(" 使用传统 for 循环: 部分和 = %d\n", sum2)
|
||
|
||
// 字符串遍历的性能
|
||
fmt.Printf(" 字符串遍历的性能考虑:\n")
|
||
longString := "这是一个包含中文字符的长字符串,用于演示遍历性能"
|
||
|
||
// 使用 range(处理 Unicode 正确)
|
||
charCount1 := 0
|
||
for range longString {
|
||
charCount1++
|
||
}
|
||
fmt.Printf(" 使用 range 统计字符数: %d\n", charCount1)
|
||
|
||
// 使用 len(字节数,不是字符数)
|
||
byteCount := len(longString)
|
||
fmt.Printf(" 使用 len 统计字节数: %d\n", byteCount)
|
||
|
||
// 使用 utf8.RuneCountInString(正确的字符数)
|
||
charCount2 := utf8.RuneCountInString(longString)
|
||
fmt.Printf(" 使用 utf8.RuneCountInString 统计字符数: %d\n", charCount2)
|
||
|
||
// 映射遍历的注意事项
|
||
fmt.Printf(" 映射遍历的注意事项:\n")
|
||
largeMap := make(map[int]string)
|
||
for i := 0; i < 10; i++ {
|
||
largeMap[i] = fmt.Sprintf("value_%d", i)
|
||
}
|
||
|
||
fmt.Printf(" 映射大小: %d\n", len(largeMap))
|
||
fmt.Printf(" 映射遍历顺序是随机的,每次运行可能不同\n")
|
||
|
||
// 显示前几个元素
|
||
count := 0
|
||
for key, value := range largeMap {
|
||
fmt.Printf(" %d: %s\n", key, value)
|
||
count++
|
||
if count >= 3 {
|
||
fmt.Printf(" ...\n")
|
||
break
|
||
}
|
||
}
|
||
|
||
fmt.Println()
|
||
}
|
||
|
||
// 辅助函数
|
||
func contains(s, substr string) bool {
|
||
for i := 0; i <= len(s)-len(substr); i++ {
|
||
if s[i:i+len(substr)] == substr {
|
||
return true
|
||
}
|
||
}
|
||
return false
|
||
}
|
||
|
||
func isNumeric(s string) bool {
|
||
if len(s) == 0 {
|
||
return false
|
||
}
|
||
for _, char := range s {
|
||
if char < '0' || char > '9' {
|
||
return false
|
||
}
|
||
}
|
||
return true
|
||
}
|
||
|
||
/*
|
||
运行这个程序:
|
||
go run 04-range.go
|
||
|
||
学习要点:
|
||
1. range 是 Go 中遍历集合类型的标准方式
|
||
2. range 可以用于数组、切片、字符串、映射和通道
|
||
3. range 返回索引/键和值,可以用 _ 忽略不需要的部分
|
||
4. range 会拷贝值,修改拷贝不会影响原始数据
|
||
5. 字符串的 range 遍历按 Unicode 字符,索引是字节位置
|
||
|
||
range 的语法:
|
||
- for index, value := range collection { ... }
|
||
- for index := range collection { ... } // 只要索引/键
|
||
- for _, value := range collection { ... } // 只要值
|
||
- for range collection { ... } // 只计数
|
||
|
||
不同类型的 range:
|
||
1. 数组/切片: 返回索引和值
|
||
2. 字符串: 返回字节位置和 Unicode 字符
|
||
3. 映射: 返回键和值(顺序随机)
|
||
4. 通道: 返回接收到的值(通道需要关闭)
|
||
|
||
性能考虑:
|
||
1. range 通常比传统 for 循环更高效和安全
|
||
2. 字符串的 range 正确处理 Unicode 字符
|
||
3. 大集合的遍历考虑提前退出
|
||
4. 映射遍历顺序是随机的
|
||
|
||
最佳实践:
|
||
1. 优先使用 range 遍历集合
|
||
2. 使用 _ 忽略不需要的返回值
|
||
3. 注意 range 的值拷贝特性
|
||
4. 字符串处理时考虑 Unicode 字符
|
||
5. 通道遍历前确保通道会被关闭
|
||
|
||
常见应用场景:
|
||
1. 数据处理和统计
|
||
2. 配置文件解析
|
||
3. 文本分析
|
||
4. 数据验证
|
||
5. 矩阵操作
|
||
6. 集合操作
|
||
*/ |