Go中new创建指针与命名返回指针差异:空指针解引用问题
Go函数返回值命名引发空指针解引用的原因
问题场景
下面这个函数签名可以正常运行:
func GetFileMetadata(f *multipart.FileHeader) *FileMetadata { d := new(FileMetadata) // ... if typ, err := GetFileRealType(f); err == nil { d.Type = typ.MIME.Value fileExt = "." + typ.Extension } else { d.Type = "unknown" } return d }
但换成带命名返回值的签名后,会触发nil pointer dereference错误:
func GetFileMetadata(f *multipart.FileHeader) (d *FileMetadata) { // ... if typ, err := GetFileRealType(f); err == nil { d.Type = typ.MIME.Value fileExt = "." + typ.Extension } else { d.Type = "unknown" } return }
原因分析
Go语言中,当你在函数签名里命名返回值时(比如这里的(d *FileMetadata)),这个变量会被自动初始化为对应类型的零值。对于指针类型来说,零值就是nil。
第一个版本的代码里,通过d := new(FileMetadata)主动为d分配了内存,得到的是一个指向FileMetadata实例的非nil指针,所以后续对d.Type的赋值是合法的。
而第二个版本里,你没有对d做任何初始化,直接去赋值d.Type——这相当于尝试对一个nil指针进行解引用操作,自然会触发空指针错误。
解决办法
两种可选方案:
- 在函数内部手动初始化
d,比如添加d = new(FileMetadata)或者d = &FileMetadata{}; - 放弃命名返回值,沿用第一个版本的写法。
内容的提问来源于stack exchange,提问作者Md. A. A. Apu
相关产品推荐
相关产品推荐

