package data import ( "encoding/gob" "fmt" "os" "sync" "time" "github.com/google/uuid" ) type Article struct { Title string Author string Created time.Time Desc string Content string Tags []string UUID uuid.UUID AuthorID int64 } // TODO: setCh type ArticleList struct { addCh chan *Article delCh chan uuid.UUID getCh chan []Article retCh chan *Article articles []*Article wg sync.WaitGroup } // TODO: setCh type TagList struct { addCh chan string getCh chan []string tags []string wg sync.WaitGroup } func initArticleList() *ArticleList { return &ArticleList{ addCh: make(chan *Article), delCh: make(chan uuid.UUID), getCh: make(chan []Article), retCh: make(chan *Article), } } func initTagList() *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 := initArticleList() list.articles = make([]*Article, 0) 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() articles := al.Get() if err = gob.NewEncoder(file).Encode(articles); 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) } articleList := initArticleList() if err = gob.NewDecoder(file).Decode(&articleList.articles); err != nil { return nil, fmt.Errorf("error decoding key: %v", err) } articleList.wg.Add(1) go articleList.start() articleList.wg.Wait() return articleList, nil } func NewTagList() *TagList { list := initTagList() list.tags = make([]string, 0) 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() tags := tl.Get() if err = gob.NewEncoder(file).Encode(tags); 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) } defer file.Close() tagList := initTagList() if err = gob.NewDecoder(file).Decode(&tagList.tags); err != nil { return nil, fmt.Errorf("error decoding key: %v", err) } tagList.wg.Add(1) go tagList.start() tagList.wg.Wait() return tagList, nil }