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条)

报告相同问题?

悬赏问题

  • ¥30 这是哪个作者做的宝宝起名网站
  • ¥60 版本过低apk如何修改可以兼容新的安卓系统
  • ¥25 由IPR导致的DRIVER_POWER_STATE_FAILURE蓝屏
  • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率
  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!