
go 语言中切片本身是引用类型,但其底层数组指针、长度和容量被封装为值;若需在函数内修改原始切片的元素(而非仅副本),需传入指向切片的指针,并显式解引用后操作。
go 语言中切片本身是引用类型,但其底层数组指针、长度和容量被封装为值;若需在函数内修改原始切片的元素(而非仅副本),需传入指向切片的指针,并显式解引用后操作。
在 Go 中,切片(slice)本质上是一个包含三个字段的结构体:指向底层数组的指针、长度(len)和容量(cap)。虽然切片能高效共享底层数组,但将切片作为参数传递时,传递的是该结构体的副本——这意味着函数内可修改其元素(因指针指向同一数组),但无法改变调用方切片变量本身的地址、长度或容量(例如 append 可能导致底层数组扩容,从而脱离原切片)。
然而,当你的目标是在函数中直接修改调用方切片变量所指向的底层数组内容(如更新某个索引的值),最直接且安全的方式是:*传入切片的指针(`[]T)**,并在函数内通过(*s)[i]` 显式解引用后赋值。
以下为正确实现:
package main
import "fmt"
func process(names *[]string) {
fmt.Println("Pre process:", *names) // 解引用打印原始切片
(*names)[1] = "modified" // 关键:先解引用,再索引赋值
}
func main() {
names := []string{"leto", "paul", "teg"}
process(&names)
fmt.Println("Post process:", names) // 输出:[leto modified teg]
}
⚠️ 注意事项:
-
*[]string是“指向切片的指针”,不是“指向字符串的指针数组”; -
names[1]报错是因为names类型是*[]string,不支持直接索引;必须写成(*names)[1],括号不可省略(解引用运算符*优先级高于[]); - 若还需动态扩容(如
append后影响原切片),则必须返回新切片并由调用方重新赋值(Go 不支持 C 风格的双重指针重绑定),例如:names = append(names, "chani")应在main中执行,或让process返回[]string并接收赋值。
✅ 总结:
要就地修改调用方切片的元素值(非结构),传 *[]T + (*s)[i] = ... 即可;若需变更切片头(长度/容量/底层数组),应采用返回新切片的函数签名(如 func modify(s []T) []T),这是更符合 Go 惯用法的设计。










