Go中结构体是值类型,赋值或传参时默认复制整个结构体;大结构体应使用指针传递以避免拷贝开销,尤其当大小超16字节、需修改字段、高频传参或存入切片/映射时。
Go中结构体是值类型,赋值或传参时默认复制整个结构体。如果结构体很大(比如含大量字段、大数组或切片底层数组),频繁复制会显著增加内存分配和CPU开销。使用指针(*T)传递结构体,实际只传递8字节(64位系统)的地址,避免数据拷贝。
以下情况建议优先使用 *Struct:
结构体自身用值还是指针,和它内部字段是否是指针无关,但设计时需注意:
[1024]byte),应考虑改为 *[1024]byte 或更合理的替代(如 []byte + make 分配)**MyStruct 通常不必要,增加间接寻址开销且降低可读性用 unsafe.Sizeof 和 fmt.Printf("%p", &v) 观察实际大小与地址变化:
unsafe.Sizeof(MyStruct{}) 查看结构体字节数(不含动态分配内存,如切片底层数组)
func f(s MyStruct) 和 func f(s *MyStruct) 在调用前后堆栈分配差异(可用 go tool compile -S 看汇编)pprof 的 heap profile 检查高频结构体是否在堆上反复分配——若本可复用却总新建,说明指针传递或对象池可能更优假设有个日志条目结构体:
type LogEntry struct {
ID int64
Time time.Time
Level string
Message string
Metadata map[string]string // 可能很大
TraceID [32]byte // 固定32字节
}
其 unsafe.Sizeof(LogEntry{}) 至少约120+字节(取决于平台对齐)。若每秒处理万级日志,用值传递会快速抬高GC压力。改成 *LogEntry 传参,并配合 sync.Pool 复用实例,可明显降低分配频次。