Go语言向io.Writer写入[]float32时触发空指针Panic求助
Go语言写入[]float32到io.Writer时触发空指针Panic问题
测试场景与代码
测试函数将JPEG图片像素转换为亮度值后,尝试调用自定义函数写入io.Writer:
func TestNewFITSImageFrom2DDataWriteFloatData(t *testing.T) { f, err := os.Open("../../images/noise16.jpeg") if err != nil { t.Errorf("Error opening image: %s", err) } defer f.Close() img, err := jpeg.Decode(f) if err != nil { t.Errorf("Error decoding image: %s", err) } bounds := img.Bounds() ex := make([][]uint32, bounds.Dx()) for x := 0; x < bounds.Dx(); x++ { col := make([]uint32, bounds.Dy()) ex[x] = col } for j := 0; j < bounds.Dy(); j++ { for i := 0; i < bounds.Dx(); i++ { r, g, b, _ := img.At(i, j).RGBA() lum := 0.299*float64(r) + 0.587*float64(g) + 0.114*float64(b) ex[i][j] = uint32(lum) } } fit := NewFITSImageFrom2DData(ex, 16, 2, int32(bounds.Dx()), int32(bounds.Dy())) var w io.Writer // 问题所在:仅声明未初始化 err = writeFloat32Array(w, fit.Data, true) if err != nil { t.Errorf("Error writing float32 array: %s", err) } }
原始写入函数实现
自定义的writeFloat32Array函数,按块写入数据并处理FITS格式的块对齐:
// Writes FITS binary body data in network byte order. // Optionally replaces NaNs with zeros for compatibility with other software func writeFloat32Array(w io.Writer, data []float32, replaceNaNs bool) error { bufLen := 16 * 1024 buff := make([]byte, bufLen) // Process the data in chunks of BUFFER_LENGTH bytes: for block := 0; block < len(data); block += (bufLen >> 2) { size := len(data) - block if size > (bufLen >> 2) { size = (bufLen >> 2) } for offset := 0; offset < size; offset++ { d := data[block+offset] if replaceNaNs && math.IsNaN(float64(d)) { d = 0 } val := math.Float32bits(d) buff[(offset<<2)+0] = byte(val >> 24) buff[(offset<<2)+1] = byte(val >> 16) buff[(offset<<2)+2] = byte(val >> 8) buff[(offset<<2)+3] = byte(val) } _, err := w.Write(buff[:(size << 2)]) // 触发Panic的位置 if err != nil { return err } } // Complete the last partial block, for strictly FITS compliant software bytesWritten := len(data) << 2 lastPartialBlock := bytesWritten % 2880 if lastPartialBlock != 0 { sb := strings.Builder{} for i := lastPartialBlock; i < 2880; i++ { sb.WriteRune(' ') } _, err := w.Write([]byte(sb.String())) if err != nil { fmt.Println(err) return err } } return nil }
触发的Panic错误
panic: runtime error: invalid memory address or nil pointer dereference [recovered] panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1 addr=0x18 pc=0x119101f]
尝试过的修改方案
改用binary包简化写入逻辑,但仍触发相同Panic:
// Writes FITS binary body data in network byte order. // Optionally replaces NaNs with zeros for compatibility with other software func writeFloat32Array(w io.Writer, data []float32, replaceNaNs bool) error { buf := new(bytes.Buffer) err := binary.Write(buf, binary.BigEndian, data) if err != nil { return err } _, err = w.Write(buf.Bytes()) // 同样触发Panic if err != nil { return err } return nil }
问题原因与解决方案
核心原因
测试代码中var w io.Writer仅声明了接口变量,但未初始化具体的实现实例,此时w为nil接口。调用w.Write()时,Go会尝试调用nil接口的方法,直接触发空指针Panic。
解决方案
初始化一个实现了io.Writer接口的具体类型实例,比如:
- 使用
bytes.Buffer作为内存缓冲区:
var w bytes.Buffer // 初始化bytes.Buffer实例 err = writeFloat32Array(&w, fit.Data, true)
- 或写入文件:
file, err := os.Create("output.fits") if err != nil { t.Errorf("Error creating file: %s", err) } defer file.Close() err = writeFloat32Array(file, fit.Data, true)
内容的提问来源于stack exchange,提问作者Micheal J. Roberts
相关产品推荐
相关产品推荐

