You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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接口的具体类型实例,比如:

  1. 使用bytes.Buffer作为内存缓冲区:
var w bytes.Buffer // 初始化bytes.Buffer实例
err = writeFloat32Array(&w, fit.Data, true)
  1. 或写入文件:
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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 11:50:22