
本文详解 Go 语言中对字符串指针进行解引用赋值的原理与机制,说明 *course = "..." 并非修改字符串底层字节,而是将新字符串值(含头部结构体)整体写入原指针所指向的内存地址。
本文详解 go 语言中对字符串指针进行解引用赋值的原理与机制,说明 *course = "..." 并非修改字符串底层字节,而是将新字符串值(含头部结构体)整体写入原指针所指向的内存地址。
在 Go 中,字符串是不可变的值类型,其底层由两个字段组成:一个指向底层字节数组的指针(uintptr)和一个长度(int)。虽然字符串内容不可变,但字符串变量本身是可变的——也就是说,你可以让一个 string 类型的变量指向不同的字符串值。
当使用 &course 获取字符串变量的地址时,得到的是一个 *string 类型的指针,它指向该变量在栈(或堆)上占据的内存空间(大小为 unsafe.Sizeof(string),通常是 16 字节)。此时,*course 并不是“字符串内容的引用”,而是对整个字符串变量的解引用——即访问该变量所存储的完整字符串结构体。
因此,语句:
<code class="go">*course = "Docker Extended"</code>
等价于:
“将字符串字面量
"Docker Extended"对应的底层结构(即数据指针 + 长度)复制到course变量当前所在的内存位置。”
这本质上是一次结构体级别的赋值(copy-by-value),而非对只读字节数组的篡改。这也是为什么该操作合法且安全:Go 允许你随时用一个新的字符串值替换旧的字符串变量,无论它是局部变量、字段,还是通过指针间接访问。
✅ 正确理解要点:
-
*course是一个左值(lvalue),可被赋值; - 赋值操作不改变原字符串内容,而是更新整个
string结构体; -
course变量的内存地址未变,但其中存储的指针和长度已更新为新字符串的值; - 若原字符串来自字符串字面量(如
"Docker Deep Dive"),其底层字节数组位于只读段,但新字符串"Docker Extended"同样作为字面量加载,其地址由编译器静态分配,无需运行时分配。
⚠️ 注意事项:
- 不要误以为
*course[0] = 'X'可行——string不支持索引赋值,这是语法错误; - 若需动态修改字符序列,请改用
[]byte或strings.Builder; - 指针传递仅用于让函数能修改调用方的变量值,不涉及字符串内容的“就地编辑”。
综上,*course = ... 是 Go 值语义下的自然体现:字符串变量可被整体替换,而指针只是提供了间接访问和修改该变量的途径。










