Go语言中使用*[]Item定义切片是否正确?切片默认为指针类型吗
Go 切片正确用法及相关写法辨析
首先先纠正一个普遍的认知偏差:切片本身不是指针类型。Go 运行时层面的切片本质是一个固定大小的结构体,仅包含三个字段:指向底层数组的指针、切片长度、切片容量,64位系统下整个结构体大小仅24字节。很多人误以为切片是指针,是因为拷贝切片时仅会拷贝这个小结构体,不会复制整个底层数组,因此通过新切片修改元素时会同步改动原切片对应的底层数组元素,但切片本身属于值类型,不是原生指针。
关于*[]Item写法的说明
- 语法层面
*[]Item是完全合法的写法,但99%的日常开发场景下都不推荐使用,也不属于常规正确写法。 - 它不是「指向指针的指针」:因为切片本身不是指针,
*[]Item代表的是指向切片结构体的指针,和二级指针没有关系,相关误解来源于「切片是指针类型」的错误前提。 - 它的适用场景极其狭窄:只有当你需要在函数内部修改切片本身的结构体字段(比如在函数内对切片做append操作,且不通过返回值传递新切片,要让调用方持有的原切片直接感知到底层数组指针、长度、容量的变化)时,才可能用到这个写法。Go 社区的通用实践是遇到这类场景直接返回修改后的新切片,而不是传切片指针,代码可读性和可维护性更好。
- 不要为了「减少拷贝开销」使用
*[]Item:切片本身的值拷贝开销只有24字节,远低于指针解引用带来的性能损耗,也会增加代码理解成本。
常规切片写法的正确性说明
你提到的两种写法都是Go语言中切片的标准正确用法,二者适用场景不同:
[]Item:值类型切片,切片内直接存储Item类型的值,是最常用的切片形式。适合Item是基础类型、小体积结构体,不需要共享元素实例、不需要在遍历/传参时修改元素内部字段的场景。[]*Item:指针类型切片,切片内存储的是指向Item实例的指针。适合Item结构体体积较大、需要在多处共享同一个Item实例、需要通过切片元素修改Item内部字段的场景。
额外提醒:注意区分「切片指针」和「指针切片」的差异,
*[]Item是切片指针,[]*Item是存储元素为指针的切片,二者语义完全不同,日常开发中99%的场景你需要的都是后者,或者普通的值切片[]Item。
内容的提问来源于stack exchange,提问作者Madhusudhan
相关产品推荐
相关产品推荐

