如何使用Golang解码Reddit的RSS? [英] How to decode Reddit's RSS using Golang?
问题描述
我一直在使用Go的XML包,因此看不到以下代码有什么问题。
I've been playing about with Go's XML package and cannot see what is wrong with the following code.
package main
import (
"encoding/xml"
"fmt"
"net/http"
)
type Channel struct {
Items Item
}
type Item struct {
Title string `xml:"title"`
Link string `xml:"link"`
Description string `xml:"description"`
}
func main() {
var items = new(Channel)
res, err := http.Get("http://www.reddit.com/r/google.xml")
if err != nil {
fmt.Printf("Error: %v\n", err)
} else {
decoded := xml.NewDecoder(res.Body)
err = decoded.Decode(items)
if err != nil {
fmt.Printf("Error: %v\n", err)
}
fmt.Printf("Title: %s\n", items.Items.Title)
}
}
上面的代码运行无误,并打印到终端:
The above code runs without any errors and prints to the terminal:
Title:
该结构似乎是空的,但我看不到为什么它没有填充XML数据。
The struct seems empty but I can't see why it isn't getting populated with the XML data.
推荐答案
您的程序已接近完成,但需要指定更多上下文来匹配XML文档。
Your program comes close, but needs to specify just a little bit more context to match the XML document.
您需要修改字段标签,以帮助引导XML绑定通过
Channel
结构传递到 Item
结构:
You need to revise your field tags to help guide the XML binding down through your
Channel
structure to your Item
structure:
type Channel struct {
Items []Item `xml:"channel>item"`
}
type Item struct {
Title string `xml:"title"`
Link string `xml:"link"`
Description string `xml:"description"`
}
每个 encoding / xml.Unmarshal()
,此处适用第七个项目符号:
Per the documentation for encoding/xml.Unmarshal()
, the seventh bullet item applies here:
如果XML元素包含名称与$ b $相匹配的子元素b标记格式为 a或 a> b> c的前缀,解组
将XML结构查找具有给定名称
的元素,并将最里面的元素映射到该结构
字段。以>开头的标记等效于以字段名开头的
,后跟>。
If the XML element contains a sub-element whose name matches the prefix of a tag formatted as "a" or "a>b>c", unmarshal will descend into the XML structure looking for elements with the given names, and will map the innermost elements to that struct field. A tag starting with ">" is equivalent to one starting with the field name followed by ">".
您的情况下,您希望遍历顶级< rss>
元素的< channel>
元素查找每个< item>
元素。不过请注意,我们实际上不需要-指定 Channel
结构应遍历顶级 < rss>
元素,方法是将 Items
字段的标签写为
In your case, you're looking to descend through the top-level <rss>
element's <channel>
elements to find each <item>
element. Note, though, that we don't need to—an in fact can't—specify that the Channel
struct should burrow through the top-level <rss>
element by writing the Items
field's tag as
`xml:"rss>channel>item"`
该上下文是隐式的;提供给 Unmarshall()
的结构已经映射到顶级XML元素。
That context is implicit; the struct supplied to Unmarshall()
already maps to the top-level XML element.
请注意,您的 Channel
结构的 Items
字段应为slice_of- Item
,而不仅仅是单个 Item
。
Note too that your Channel
struct's Items
field should be of type slice-of-Item
, not just a single Item
.
您提到您很难使该建议生效。这是一个完整的清单,我发现它可以像人们期望的那样工作:
You mentioned that you're having trouble getting the proposal to work. Here's a complete listing that I find works as one would expect:
package main
import (
"encoding/xml"
"fmt"
"net/http"
"os"
)
type Channel struct {
Items []Item `xml:"channel>item"`
}
type Item struct {
Title string `xml:"title"`
Link string `xml:"link"`
Description string `xml:"description"`
}
func main() {
if res, err := http.Get("http://www.reddit.com/r/google.xml"); err != nil {
fmt.Println("Error retrieving resource:", err)
os.Exit(1)
} else {
channel := Channel{}
if err := xml.NewDecoder(res.Body).Decode(&channel); err != nil {
fmt.Println("Error:", err)
os.Exit(1)
} else if len(channel.Items) != 0 {
item := channel.Items[0]
fmt.Println("First title:", item.Title)
fmt.Println("First link:", item.Link)
fmt.Println("First description:", item.Description)
}
}
}
这篇关于如何使用Golang解码Reddit的RSS?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!