我是 Golang 的新手,遇到了以下问题。


// XXX a bit inefficient. could open r files and run over list once

for r := 0; r < nreduce; r++ {

    file, err = os.Create(ReduceName(fileName, JobNumber, r))

    if err != nil {

        log.Fatal("DoMap: create ", err)

    }

    enc := json.NewEncoder(file)

    for e := res.Front(); e != nil; e = e.Next() {

        kv := e.Value.(KeyValue)

        if ihash(kv.Key)%uint32(nreduce) == uint32(r) {

            err := enc.Encode(&kv)

            if err != nil {

                log.Fatal("DoMap: marshall ", err)

            }

        }

    }

    file.Close()

}

基本上,这段代码片段在每个 for 循环迭代中创建一个文件,然后根据(键,值)对打开一个文件以对属于该文件的内容进行编码。然而,这段代码效率低下,因为它扫描了这个文件太多次。更有效的方法是打开 r 文件并运行此列表文件一次。所以我想这样写(但我不知道怎么写):


enc_map := make(map[int]*Encode)

for r := 0; r < nreduce; r++ {

file. err = os.Create(ReduceName(fileName, JobNumber, r))

if err != nil {

    log.Fatal("DoMap: create ", err)

}

enc := json.NewEncoder(file)

enc_map[r] = enc

for e := res.Front(); e != nil; e = e.Next() {

    kv := e.Value.(KeyValue)

    r := ihash(kv.Key)&uint32(nreduce) 

    err := enc_map[r].Encode(&kv)

    if err != nil {

        log.Fatal("DoMap: marshall ", err)

    }

}

此代码片段首先创建一个保存 json.Encoder 对象的映射,然后遍历此文件一次。我查看了 go 文档,它说 json.Encoder 的类型名称是 *Encode。但是线


enc_map := make(map[int]*Encode)

是错误的,编译器给了我以下错误:


../mapreduce/mapreduce.go:228: undefined: Encode

../mapreduce/mapreduce.go:230: file.err undefined (type *os.File has no field or method err)

../mapreduce/mapreduce.go:230: multiple-value os.Create() in single-value context

那么做事的正确方法是什么?