go 的切片是动态数组,支持通过 append 自动扩容,因此在遍历字符串筛选字符时完全无需预先统计数量再分配内存,单次循环即可完成索引、收集和过滤。
在 Go 中,初学者(尤其是从 Python 转来的开发者)常误以为切片像传统数组一样需要预先确定长度——但事实恰恰相反:Go 的切片(slice)本质上是动态的引用类型,底层由数组、长度(len)和容量(cap)三部分构成,append 会自动处理内存分配与扩容(类似 Python 的 list.append())。因此,你完全不需要“先遍历计数、再遍历填充”的两阶段模式。
以下是你原函数的更简洁、更符合 Go 惯用法(idiomatic Go)的重构版本:
import (
"strings"
"unicode"
)
func removeAndIndexPunctuation(word string) (string, []rune, []int) {
var punctuations []rune
var indexes []int
var cleanRunes []rune
for i, char := range word {
if unicode.IsPunct(char) {
punctuations = append(punctuations, char)
indexes = append(indexes, i)
} else {
cleanRunes = append(cleanRunes, char)
}
}
return string(cleanRunes), punctuations, indexes
}✅ 优势说明:

⚠️ 注意事项:
总之,Go 的切片不是“静态数组”,而是具备动态能力的高级抽象。拥抱 append 和零长度切片([]T{} 或 var s []T),是写出简洁、健壮 Go 代码的关键一步。