Go 的 string 底层是只读字节切片(指针 + 长度),内容不可修改。不可变性带来三个好处:string 可以安全地在 goroutine 间共享而无需加锁;可以作为 map 的 key;子串切分等操作可以低拷贝实现。

string 按 UTF-8 编码存储字节。len(s) 返回字节数而非字符数;s[i] 取到的是 byte;for range 遍历会按 UTF-8 解码出 rune(int32,即 Unicode 码点),索引是字节偏移。修改字符串必须先转成 []rune(按字符)或 []byte(按字节),改完再转回,转换会产生拷贝。

s := "Go语言"
fmt.Println(len(s)) // 8:2 字节 + 2 个汉字各 3 字节
r := []rune(s)
r[2] = '之'
fmt.Println(string(r)) // Go之语

易错点:用 []byte 改含中文的字符串会切坏多字节编码;频繁拼接用 strings.Builder 而不是 +=。追问方向:string 与 []byte 转换的编译器零拷贝优化、range 遇到非法 UTF-8 的行为。