doxqszx09742 2014-07-28 15:50
浏览 256
已采纳

在Go中读取CSV文件

I'm learning Go. Here is a code snippet that reads CSV file:

func parseLocation(file string) (map[string]Point, error) {
    f, err := os.Open(file)
    defer f.Close()
    if err != nil {
        return nil, err
    }
    lines, err := csv.NewReader(f).ReadAll()
    if err != nil {
        return nil, err
    }
    locations := make(map[string]Point)
    for _, line := range lines {
        name := line[0]
        lat, laterr := strconv.ParseFloat(line[1], 64)
        if laterr != nil {
            return nil, laterr
        }
        lon, lonerr := strconv.ParseFloat(line[2], 64)
        if lonerr != nil {
            return nil, lonerr
        }
        locations[name] = Point{lat, lon}
    }
    return locations, nil
}

Is there a way to improve readability of this code? if and nil noise.

  • 写回答

3条回答 默认 最新

  • doutouman6245 2014-07-28 16:04
    关注

    Go is a very verbose language, however you could use something like this:

    // predeclare err
    func parseLocation(file string) (locations map[string]*Point, err error) {
        f, err := os.Open(file)
        if err != nil {
            return nil, err
        }
        defer f.Close() // this needs to be after the err check
    
        lines, err := csv.NewReader(f).ReadAll()
        if err != nil {
            return nil, err
        }
    
        //already defined in declaration, no need for :=
        locations = make(map[string]*Point, len(lines))
        var lat, lon float64 //predeclare lat, lon
        for _, line := range lines {
            // shorter, cleaner and since we already have lat and err declared, we can do this.
            if lat, err = strconv.ParseFloat(line[1], 64); err != nil {
                return nil, err
            }
            if lon, err = strconv.ParseFloat(line[2], 64); err != nil {
                return nil, err
            }
            locations[line[0]] = &Point{lat, lon}
        }
        return locations, nil
    }
    

    //edit

    A more efficient and proper version was posted by @Dustin in the comments, I'm adding it here for completeness sake:

    func parseLocation(file string) (map[string]*Point, error) {
        f, err := os.Open(file)
        if err != nil {
            return nil, err
        }
        defer f.Close()
    
        csvr := csv.NewReader(f)
    
        locations := map[string]*Point{}
        for {
            row, err := csvr.Read()
            if err != nil {
                if err == io.EOF {
                    err = nil
                }
                return locations, err
            }
    
            p := &Point{}
            if p.lat, err = strconv.ParseFloat(row[1], 64); err != nil {
                return nil, err
            }
            if p.lon, err = strconv.ParseFloat(row[2], 64); err != nil {
                return nil, err
            }
            locations[row[0]] = p
        }
    }
    

    <kbd>playground</kbd>

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥15 求lingo代码和思路
  • ¥15 公交车和无人机协同运输
  • ¥15 stm32代码移植没反应
  • ¥15 matlab基于pde算法图像修复,为什么只能对示例图像有效
  • ¥100 连续两帧图像高速减法
  • ¥15 如何绘制动力学系统的相图
  • ¥15 对接wps接口实现获取元数据
  • ¥20 给自己本科IT专业毕业的妹m找个实习工作
  • ¥15 用友U8:向一个无法连接的网络尝试了一个套接字操作,如何解决?
  • ¥30 我的代码按理说完成了模型的搭建、训练、验证测试等工作(标签-网络|关键词-变化检测)