package rss import ( "encoding/gob" "encoding/xml" "fmt" "os" "sync" ) type Feed struct { addChannel chan *Channel XMLName xml.Name `xml:"rss"` Version string `xml:"version,attr"` ContentNamespace string `xml:"xmlns:content,attr"` Channels []*Channel wg sync.WaitGroup } func (f *Feed) start() { f.wg.Done() for channel := range f.addChannel { f.Channels = append(f.Channels, channel) } } func initFeed() *Feed { feed := &Feed{ addChannel: make(chan *Channel), Version: "2.0", ContentNamespace: "http://purl.org/rss/1.0/modules/content/", } return feed } func (f *Feed) check() error { if f.Channels == nil { return fmt.Errorf("error: feed has no channels") } for _, channel := range f.Channels { if err := channel.check(); err != nil { return fmt.Errorf("error checking channel: %v", err) } } return nil } func NewFeed() *Feed { feed := initFeed() feed.wg.Add(1) go feed.start() feed.wg.Wait() return feed } func (f *Feed) AddChannel(c *Channel) { f.addChannel <- c } func (f *Feed) Save(filename string) error { file, err := os.Create(filename) if err != nil { return fmt.Errorf("error creating file %v: %v", filename, err) } defer file.Close() if err := gob.NewEncoder(file).Encode(f); err != nil { return fmt.Errorf("error encoding feed in file %v: %v", filename, err) } return nil } func OpenFeed(filename string) (*Feed, error) { file, err := os.Open(filename) if err != nil { return nil, fmt.Errorf("error opening file %v: %v", filename, err) } defer file.Close() feed := initFeed() feed.wg.Add(1) go feed.start() feed.wg.Wait() if err := gob.NewDecoder(file).Decode(feed); err != nil { return nil, fmt.Errorf("error decoding file %v: %v", filename, err) } return nil, nil }