如何迭代遍历解码器?

huangapple go评论89阅读模式
英文:

How can I iterate over a Decoder?

问题

我来自Python背景,所以有倾向于以迭代器的方式思考。在Go语言中,range关键字似乎意味着我们可以以几乎相同的方式思考,因此我想在Go语言中实现与Python代码在语义上等效的功能:

for obj := range jsonDecoder {
    // 业务逻辑
}

以下是在Go语言中的示例代码:

func (c *GorpController) Create(dec *json.Decoder) {
    // 业务逻辑
}

我希望能够这样实现:

for someValue := range dec {
    // 业务逻辑
}

是否有一种方法可以在Decoder接口中使用range?最理想的情况是使用一个不同的接口对其进行包装,符合惯用模式也可以接受。

谢谢!

英文:

I come from a Python background and so have a tendency to think in terms of iterators. It seems to me that the range keyword in Go intends for us to think in a nearly identical way, so I would like to do somthing semantically equivalent to this Python code in Go:

for obj in json_decoder:
    # business logic

Here is the motivating case in Go; consider the following function:

func (c *GorpController) Create(dec *json.Decoder) {
    // business logic
}

I would like to be able to implement it as:

for someValue := range dec {
    // business logic
}

Is there some sort of way to use range with a Decoder interface? A function that wraps it in a different interface would be ideal, and an idiomatic pattern would be acceptable.

Thank you!

答案1

得分: 3

很抱歉,你只能在“数组、切片、字符串、映射或从通道读取”时使用range(参见effective go)。

为了在解码时迭代结构体,文档建议使用以下方法:

dec := json.NewDecoder(strings.NewReader(jsonStream))
for {
    var m Message
    if err := dec.Decode(&m); err == io.EOF {
        break
    } else if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("%s: %s\n", m.Name, m.Text)
}

(直接摘自官方文档示例

英文:

Unfortunately, you can only use range with an "array, slice, string, or map, or reading from a channel" (see effective go)

to iterate over structs as they get decoded, the documentation recommends doing:

dec := json.NewDecoder(strings.NewReader(jsonStream))
for {
	var m Message
	if err := dec.Decode(&m); err == io.EOF {
		break
	} else if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s: %s\n", m.Name, m.Text)
}

(taken directly from the official doc example)

答案2

得分: 1

json.Decoder是一个结构体,在Go语言中,你只能对字符串、切片/数组、映射和通道(https://golang.org/ref/spec#For_statements)使用range进行迭代。

然而,你可以遍历io.Reader中的所有JSON编码值:

func main() {
    s := `"a string"
72
["an", "array"]
{"an": "object"}
`
    dec := json.NewDecoder(strings.NewReader(s))
    for {
        var v interface{}
        if err := dec.Decode(&v); err != nil {
            if err == io.EOF {
                break
            }
            log.Fatal(err)
        }
        log.Print(v)
    }
}

http://play.golang.org/p/flqXlcx_6B

编辑:尽管More在这个例子中似乎可以工作,但根据godoc的说明,这不是它的预期用法,因此检查err == io.EOF会更好。已更新代码片段。

英文:

A json.Decoder is a struct, and in Go, you can only iterate (use range) over strings, slices/arrays, maps and channels (https://golang.org/ref/spec#For_statements).

You can, however, loop over all JSON-encoded values in an io.Reader:

func main() {
	s := `"a string"
72
["an", "array"]
{"an": "object"}
`
	dec := json.NewDecoder(strings.NewReader(s))
	for {
		var v interface{}
		if err := dec.Decode(&v); err != nil {
			if err == io.EOF {
				break
			}
			log.Fatal(err)
		}
		log.Print(v)
	}
}

http://play.golang.org/p/flqXlcx_6B

EDIT: although More does seem to work for values as in this example, it is not its intended usage (based on the godoc), so checking for err == io.EOF would be better. Updated the code snippet.

huangapple
  • 本文由 发表于 2015年11月11日 03:35:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/33638113.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定