Golang应用中收集产品信息时遇到的问题

Golang应用中收集产品信息时遇到的问题 我编写了一个应用程序(这是我第一次用Golang编写的任何东西),遇到了一些问题。简而言之,我使用生成的swagger规范从我们工作中使用的产品(Rapid7产品)中提取信息。它在我们的一个实例上运行良好,但在另一个实例上出现错误:

	panic: runtime error: index out of range

	goroutine 1 [running]:
	main.ToCsv(0x0, 0x0, 0x0, 0x13451c0, 0xc4202a0030)
	        /Users/test/workspace/GoLangIVMCollector/InsightVM_Data.go:307 +0xc63
	main.main()
	        /Users/test/workspace/GoLangIVMCollector/InsightVM_Data.go:475 +0xe39

我认为(如果需要我可以发布其余部分)这是故障排除所需的代码:

func ToCsv(inputs []interface{}, output io.Writer) {
	w := csv.NewWriter(output)
	defer w.Flush()

	// Get Header
	r := reflect.ValueOf(inputs[0])
	val := reflect.Indirect(reflect.ValueOf(inputs[0]))
	var headers []string
	for i := 0; i < r.NumField(); i++ {
		headers = append(headers, val.Type().Field(i).Name)
	}
	w.Write(headers)

	// Get Content
	for _, input := range inputs {
		ri := reflect.ValueOf(input)

		var result []string
		for i := 0; i < ri.NumField(); i++ {
			switch ri.Field(i).Interface().(type) {
			case bool:
				result = append(result, strconv.FormatBool(ri.Field(i).Interface().(bool)))
			case int32:
				result = append(result, strconv.FormatInt(int64(ri.Field(i).Interface().(int32)), 10))
			case string:
				result = append(result, ri.Field(i).Interface().(string))
			default:
				result = append(result, "")
			}
		}
		w.Write(result)
	}
}

这是使用此函数的另一个函数:

	// Reports
	reports, err := GetAllReports(r7vm)
	var structuredReports []interface{}

	if err != nil {
		log.Fatal(fmt.Sprintf("Failed to retrieve reports: %s", err))
	} else {
		fmt.Println("Gathering Report Information...")
		for _, report := range reports {
			structuredReports = append(structuredReports, structs.CreateReport(report))
		}

		file, _ := os.Create(fmt.Sprintf("%sreports.csv", dir))
		defer file.Close()
		ToCsv(structuredReports, file)
	}

错误发生在以下行(初始错误中的第307行):

r := reflect.ValueOf(inputs[0])

第二个错误是因为我在上面的第二个代码块底部使用了该ToCSV函数。我拉取的JSON链接在这里:https://pastebin.com/m7SGiaYV

简而言之:调用API,获取上述JSON返回,尝试使用上面链接的函数将其放入CSV,出现上述错误。如果需要更多信息,请告诉我。

编辑:刚刚尝试简单地将拉取结果打印到控制台,但什么也没得到。我认为这与我对结果进行分页的方式有关。


更多关于Golang应用中收集产品信息时遇到的问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html

3 回复

tehreet:

r := reflect.ValueOf(inputs[0])

这是InsightVM_Data.go的第307行吗?

我推测你的inputs是空的,因此无法访问元素0。请先进行长度检查。

更多关于Golang应用中收集产品信息时遇到的问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


你好

问题出现在ToCsv函数中的inputs[0]索引访问,当inputs切片为空时会导致"index out of range"错误。从错误堆栈可以看出,structuredReports切片可能为空。

以下是修复后的代码:

func ToCsv(inputs []interface{}, output io.Writer) error {
    if len(inputs) == 0 {
        return fmt.Errorf("inputs slice is empty")
    }
    
    w := csv.NewWriter(output)
    defer w.Flush()

    // Get Header
    r := reflect.ValueOf(inputs[0])
    val := reflect.Indirect(reflect.ValueOf(inputs[0]))
    var headers []string
    for i := 0; i < r.NumField(); i++ {
        headers = append(headers, val.Type().Field(i).Name)
    }
    if err := w.Write(headers); err != nil {
        return err
    }

    // Get Content
    for _, input := range inputs {
        ri := reflect.ValueOf(input)

        var result []string
        for i := 0; i < ri.NumField(); i++ {
            switch ri.Field(i).Interface().(type) {
            case bool:
                result = append(result, strconv.FormatBool(ri.Field(i).Interface().(bool)))
            case int32:
                result = append(result, strconv.FormatInt(int64(ri.Field(i).Interface().(int32)), 10))
            case string:
                result = append(result, ri.Field(i).Interface().(string))
            default:
                result = append(result, "")
            }
        }
        if err := w.Write(result); err != nil {
            return err
        }
    }
    return nil
}

调用代码也需要相应修改:

// Reports
reports, err := GetAllReports(r7vm)
var structuredReports []interface{}

if err != nil {
    log.Fatal(fmt.Sprintf("Failed to retrieve reports: %s", err))
} else {
    fmt.Println("Gathering Report Information...")
    for _, report := range reports {
        structuredReports = append(structuredReports, structs.CreateReport(report))
    }

    if len(structuredReports) > 0 {
        file, _ := os.Create(fmt.Sprintf("%sreports.csv", dir))
        defer file.Close()
        if err := ToCsv(structuredReports, file); err != nil {
            log.Printf("Failed to write CSV: %v", err)
        }
    } else {
        fmt.Println("No reports data to process")
    }
}

主要修改:

  1. ToCsv函数开头添加空切片检查
  2. 添加错误处理返回值
  3. 在调用代码中检查structuredReports是否为空
  4. 处理CSV写入错误

问题根源可能是GetAllReports返回空结果或分页逻辑有问题,建议检查API响应数据。

回到顶部