不能直接用[]byte反转字符串,因为go中string是utf-8编码的字节序列,中文、emoji等多字节字符会被截断导致乱码或panic;必须先转为[]rune按unicode码点反转,再转回string。

为什么不能直接用 byte 切片反转字符串?
Go 的字符串底层是只读的 byte 序列,但很多字符(比如中文、emoji)占多个字节。直接按 byte 反转会导致乱码,例如 "你好" 变成无效 UTF-8 字节序列。
真正要反转的是 Unicode 码点(即 rune),不是字节。所以必须先转成 []rune,再操作。
- 错误做法:
[]byte(s)+ 双指针 → 乱码或 panic(非法 UTF-8) - 正确前提:
str := "?世界"→runeSlice := []rune(str)才安全 - 注意:
rune是 int32,切片转换有内存开销,但这是 UTF-8 安全性的必要代价
双指针反转 []rune 的标准写法
和数组反转一样,首尾交换,向中间收缩。没有魔法,但要注意边界和索引计算。
示例:
func reverseString(s string) string {
runes := []rune(s)
left, right := 0, len(runes)-1
for left
left 是终止条件,等于时无需交换(奇数长度中间元素不动)- 别写成
left —— 会多换一次,结果不变但逻辑冗余 -
string(runes)是唯一安全的还原方式;不能用string([]byte{...})
性能敏感场景下要不要复用 []rune 缓冲区?
如果高频调用(如日志处理、协议解析),反复分配 []rune 会产生 GC 压力。可考虑 sync.Pool 或预分配缓冲区。
- 简单复用:定义
var runePool = sync.Pool{New: func() interface{} { return make([]rune, 0, 64) }} - 取用:
buf := runePool.Get().([]rune)→buf = buf[:0]→buf = append(buf, []rune(s)...) - 归还:
runePool.Put(buf)—— 注意必须在函数末尾,且不能逃逸到 goroutine 外 - 但普通业务代码没必要;只有压测确认
[]rune分配成为瓶颈时才值得加
遇到 invalid memory address or nil pointer dereference 怎么排查?
这个 panic 通常不是反转逻辑出错,而是传入了 nil 字符串或未初始化变量,但 Go 中字符串字面量不可能为 nil —— 真正来源往往是接口类型断言失败或结构体字段未赋值。
- 检查调用链:是否从
interface{}断言得到string,但实际是nil? - 检查结构体字段:
type Req struct { Text *string }→req.Text可能为nil,解引用前要判空 - 最简防御:
if s == "" { return s }不解决根本问题,但能避免部分 panic 表象
真正容易被忽略的是:字符串反转本身很稳,出问题几乎全是上游数据没校验好。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











