Go 中 string 类型不可修改,底层为只读结构体{ptr *byte, len int};所有“修改”需转为[]byte操作后再转回,strings包函数均返回新字符串。
string 类型本身不可修改是的,string 在 Go 中是只读的底层字节数组(实际是只读的 struct{ptr *byte, len int}),一旦创建就不能通过下标或切片方式直接改写内容。这不是语法限制,而是运行时行为:尝试 s[0] = 'x' 会编译报错 cannot assign to s[0]。
string 是值类型,但其内部指针指向的数据不可变string 或转成 []byte 后操作[]byte
这是最常用也最安全的做法——把 string 显式转为可写的字节切片,修改后再转回 string。注意:转换有拷贝开销,且仅适用于 UTF-8 兼容场景(不推荐用于含无效 UTF-8 的二进制数据)。
str := "hello" b := []byte(str) // 拷贝一份字节 b[0] = 'H' str = string(b) // 再转回 string
[]byte(s) 都分配新底层数组,大字符串要注意性能
strings.Builder 或拼接替代全量转换string 直接取地址再转 *[]byte 来绕过——Go 1.22+ 会 panic,旧版本行为未定义且危险strings.Replace 等函数不改变原字符串?因为所有 strings 包函数都遵循不可变原则:输入 string,输出新 string。它们内部可能用 []byte 或 strings.Builder 构建结果,但绝不修改入参。
s := "aabbcc" s = strings.Replace(s, "bb", "xx", 1) // 返回新字符串,s 被重新赋值
str.replace(inplace=True) 选项strings.Builder 累积写入,避免多次分配regexp.ReplaceAllString)同理,也是纯函数式设计unsafe.String 能绕过不可变性unsafe.String 只是用来从 []byte 快速构造 string(避免一次拷贝),它**不提供写权限**。拿它生成的 string 依然不可修改,且若源 []byte 后续被改,该 string 内容可能意外变化(悬垂引用)。
unsafe.String + 修改底层数组来“伪造可变字符串”——这破坏内存安全,Go 运行时可能崩溃或产生未定义行为strings.Builder、bytes.Buffer 或自定义结构体封装 []byte
unsafe 打破这个边界。