dongyin2390 2015-09-25 00:02
浏览 36
已采纳

在Go中使用C样式迭代器的惯用方式

I'm very new to Go programming (3-4 days), and I'm trying to write some code that reads a binary file using an existing third-party C library using cgo. The C library's way of doing this seems fairly standard (for C). Slightly simplified it looks like:

int main(int argc, char *argv[]) {
    file_t *file = file_open(filename);
    index_t *index = index_load(file, filename);
    iterator_t *iter = query(idx, header, region);
    record_t *record = record_init();

    while (iterator_next(file, iter, record) >= 0) {
        /* Do stuff with record */
    }

    iterator_destroy(iter);
    record_destroy(record);
    file_close(file);

    return 0;
}

I have written the following Go code:

func main() {
    file := Open(filename)
    record := NewRecord()
    iter := file.Query(region)
    for {
        n, err := file.Next(iter, record)
        if err != nil {
            log.Fatal(err)
        }
        if n <= 0 {
            // No more records to read.
            break
        }
    }
}

This works, in the sense that it will allow me to access the records in a particular query region.

My question is whether this is an idiomatic way to approach this task in Go, or are there better alternatives? I've seen sites such as http://ewencp.org/blog/golang-iterators, but seem unable to get these examples to work with the C library (I was thinking it may be because the C library is reusing the record_t variable on each iteration rather than creating a new variable, but maybe it's just my lack of experience with Go).

  • 写回答

1条回答 默认 最新

  • doure5236 2015-09-27 20:12
    关注

    What you're doing isn't that different from moving through a file with an io.Reader:

    err, n := error(nil), 0
    for err == nil {
        err, n = f.Read(in)
        // ...do stuff with in[:n]...
    }
    

    Or using (*bufio.Scanner).Scan() (see the docs):

    for scanner.Scan() {
        // ...do something with scanner.Text()...
    }
    if err := scanner.Err(); err != nil {
        log.Fatalln(err)
    }
    

    I think you rarely want the more exotic iterator options in the blog post you linked to, the ones with closures or channels. Channels in particular invoke a lot of machinery meant for coordinating real threaded workloads, and in terms of convention, it's just typical in Go for loops to look a little different depending on what they're iterating. (In that respect, it's like iteration in C, but different from (say) Python, C++, or Java.)

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 用Multisim设计汽车尾灯控制电路
  • ¥100 求用matlab求解上述微分方程的程序代码
  • ¥15 请问各位,如何在Jetson nano主控板的Ubuntu系统中安装PyQt5
  • ¥15 MAC安装佳能LBP2900驱动的网盘提取码
  • ¥400 微信停车小程序谁懂的来
  • ¥15 ATAC测序到底用什么peak文件做Diffbind差异分析
  • ¥15 安装ubantu过程中第一个vfat 文件挂载失败
  • ¥20 GZ::CTF如何兼容一些靶机?
  • ¥15 etcd集群部署问题
  • ¥20 谁可以帮我一下问一下各位