
go 中切片本身是引用类型,但函数参数传递仍是值传递;若想在函数内修改原始切片(如长度、底层数组内容),需解引用指针参数并直接赋值给 *items,而非重新赋值指针本身。
在 Go 中,切片([]T)是一个包含三个字段的结构体:指向底层数组的指针、长度(len)和容量(cap)。虽然它“表现得像引用类型”,但作为函数参数传递时,仍是按值拷贝该结构体。因此,仅传入切片指针([]string)并不自动让函数能修改调用方的原始切片——你必须显式地通过解引用(items)来更新其内容。
回到你的示例代码:
func GetItems(items *[]string) {
list := make([]string, 0)
list = append(list, "ok")
items = &list // ❌ 错误:只改变了形参 items 的指向,不影响调用方
}这里 items = &list 只是让形参 items 指向了新局部变量 list 的地址,而原始 &items(即主函数中的 items 变量地址)并未被写入任何新值。因此主函数中 items 仍为 nil 或空切片。
✅ 正确做法是:*将新切片值赋给 `items`**,即修改指针所指向的原始切片变量本身:
func GetItems(items *[]string) {
list := make([]string, 0)
list = append(list, "ok")
*items = list // ✅ 正确:将 list 赋值给 items 所指向的变量
}完整可运行示例:
package main
import "fmt"
func GetItems(items *[]string) {
list := make([]string, 0, 1) // 预分配容量,更高效
list = append(list, "ok")
*items = list // 关键:解引用后赋值
}
func main() {
var items []string
GetItems(&items)
fmt.Println(len(items)) // 输出: 1
fmt.Println(items[0]) // 输出: "ok"
}⚠️ 注意事项:
- 若原切片非 nil 且有容量,也可直接在 *items 上追加:*items = append(*items, "ok"),避免额外分配;
- 除非必要(如需动态构造全新切片并替换原变量),否则优先考虑返回切片(func() []string)而非使用指针参数——更符合 Go 的惯用风格;
- 使用 *[]T 参数易引发理解偏差,建议辅以清晰注释或封装为结构体方法提升可读性。
总结:要通过指针“返回”切片,本质是就地更新指针所指向的切片变量,核心操作永远是 *ptr = newSlice,而非 ptr = &newSlice。










