package data import ( "encoding/gob" "fmt" "os" "sync" "time" "github.com/google/uuid" ) type Article struct { Tags *TagList Title string Author string Created time.Time Desc string Content string UUID uuid.UUID AuthorID int64 } type ArticleList struct { addCh chan *Article delCh chan uuid.UUID retCh chan *Article getCh chan []Article articles []*Article wg sync.WaitGroup } type TagList struct { addCh chan string getCh chan []string tags []string wg sync.WaitGroup } func minArticleList() *ArticleList { return &ArticleList{ addCh: make(chan *Article), delCh: make(chan uuid.UUID), retCh: make(chan *Article), getCh: make(chan []Article), } } func minTagList() *TagList { return &TagList{ addCh: make(chan string), getCh: make(chan []string), } } func (al *ArticleList) start() { al.wg.Done() for { select { case article := <-al.addCh: al.articles = append(al.articles, article) case uuid := <-al.delCh: for i, article := range al.articles { if article.UUID == uuid { al.articles = append(al.articles[:i], al.articles[i+1:]...) al.retCh <- article } } case al.getCh <- func() []Article { var list []Article for _, article := range al.articles { list = append(list, *article) } return list }(): } } } func (tl *TagList) start() { tl.wg.Done() for { select { case tag := <-tl.addCh: tl.tags = append(tl.tags, tag) case tl.getCh <- tl.tags: } } } func NewArticleList() *ArticleList { list := minArticleList() list.articles = []*Article{} list.wg.Add(1) go list.start() list.wg.Wait() return list } func (al *ArticleList) Add(a *Article) { al.addCh <- a } func (al *ArticleList) Release(uuid uuid.UUID) (*Article, bool) { al.delCh <- uuid article := <-al.retCh if article == nil { return nil, false } return article, true } func (al *ArticleList) Get() []Article { return <-al.getCh } func (al *ArticleList) Save(filename string) error { file, err := os.Create(filename) if err != nil { return fmt.Errorf("error creating key file: %v", err) } defer file.Close() encoder := gob.NewEncoder(file) articles := al.Get() err = encoder.Encode(articles) if err != nil { return fmt.Errorf("error ecoding key: %v", err) } return nil } func LoadArticleList(filename string) (*ArticleList, error) { file, err := os.Open(filename) if err != nil { return nil, fmt.Errorf("error opening key file: %v", err) } decoder := gob.NewDecoder(file) articleList := NewArticleList() err = decoder.Decode(&articleList.articles) if err != nil { return nil, fmt.Errorf("error decoding key: %v", err) } return articleList, nil } func NewTagList() *TagList { list := minTagList() list.tags = []string{} list.wg.Add(1) go list.start() list.wg.Wait() return list } func (tl *TagList) Add(tag string) { tl.addCh <- tag } func (tl *TagList) Get() []string { return <-tl.getCh } func (tl *TagList) Save(filename string) error { file, err := os.Create(filename) if err != nil { return fmt.Errorf("error creating key file: %v", err) } defer file.Close() encoder := gob.NewEncoder(file) tags := tl.Get() err = encoder.Encode(tags) if err != nil { return fmt.Errorf("error ecoding key: %v", err) } return nil } func LoadTagList(filename string) (*TagList, error) { file, err := os.Open(filename) if err != nil { return nil, fmt.Errorf("error opening key file: %v", err) } decoder := gob.NewDecoder(file) tagList := NewTagList() err = decoder.Decode(&tagList.tags) if err != nil { return nil, fmt.Errorf("error decoding key: %v", err) } return tagList, nil }