英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论