V
V
vgrabkowot2020-07-23 19:35:07
go
vgrabkowot, 2020-07-23 19:35:07

Am I doing the right thing with memory?

I'm trying to write thread-safe data manipulation. Came out to this:

package storage

import (
  "errors"
  "sort"
  "sync"
)

type Book struct {
  r sync.RWMutex

  name        string
  description string
  chapters    []Chapter
}

type Chapter struct {
  SerialNumber int64
  Name         string
  Value        string
}

func LoadBook(name, description string) *Book {
  return &Book{name: name, description: description}
}

func (b *Book) GetName() string {
  b.r.RLock()
  defer b.r.RUnlock()
  return b.name
}

func (b *Book) GetDescription() string {
  b.r.RLock()
  defer b.r.RUnlock()
  return b.description
}

func (b *Book) GetListChapters() map[string]int64 {
  m := map[string]int64{}
  b.r.RLock()
  for _, v := range b.chapters {
    m[v.Name] = v.SerialNumber
  }
  b.r.RUnlock()
  return m
}

func (b *Book) NormalizeChapters() {
  b.r.Lock()
  defer b.r.Unlock()
  sort.SliceStable(b.chapters, func(i, j int) bool {
    return b.chapters[i].SerialNumber < b.chapters[j].SerialNumber
  })
}

func (b *Book) NewChapter(name, value string) error {
  c := Chapter{
    SerialNumber: b.GetMaxSerialNumber() + 1,
    Name:         name,
    Value:        value,
  }
  if !b.ChapterSerialNumberIsQnique(c.SerialNumber) {
    return errors.New("SerialNumber not qnique")
  }
  b.r.Lock()
  defer b.r.Unlock()
  b.chapters = append(b.chapters, c)
  return nil
}

func (b *Book) ChapterSerialNumberIsQnique(serialNumber int64) bool {
  b.r.RLock()
  defer b.r.RUnlock()
  for _, v := range b.chapters {
    if v.SerialNumber == serialNumber {
      return false
    }
  }
  return true
}

func (b *Book) UpdateChapter(c Chapter) error {
  b.r.Lock()
  defer b.r.Unlock()

  for k, v := range b.chapters {
    if v.SerialNumber == c.SerialNumber {
      b.chapters[k] = c
      return nil
    }
  }
  return errors.New("Chapter not found")
}

func (b *Book) UpdateChapterByName(name, value string) error {
  b.r.Lock()
  defer b.r.Unlock()

  for k, v := range b.chapters {
    if v.Name == name {
      b.chapters[k].Value = value
      return nil
    }
  }
  return errors.New("Chapter not found")
}

func (b *Book) DeleteChapter(serialNumber int64) {
  b.r.Lock()
  defer b.r.Unlock()

  for k, v := range b.chapters {
    if v.SerialNumber == serialNumber {
      b.chapters = append(b.chapters[:k], b.chapters[k+1:]...)
    }
  }
}

func (b *Book) DeleteChapterByName(name string) {
  b.r.Lock()
  defer b.r.Unlock()

  for k, v := range b.chapters {
    if v.Name == name {
      b.chapters = append(b.chapters[:k], b.chapters[k+1:]...)
    }
  }
}

func (b *Book) GetChapter(serialNumber int64) (Chapter, bool) {
  b.r.RLock()
  defer b.r.RUnlock()

  for _, v := range b.chapters {
    if v.SerialNumber == serialNumber {
      return v, true
    }
  }
  return Chapter{}, false
}

func (b *Book) GetChapterByName(name string) (Chapter, bool) {
  b.r.RLock()
  defer b.r.RUnlock()

  for _, v := range b.chapters {
    if v.Name == name {
      return v, true
    }
  }
  return Chapter{}, false
}

func (b *Book) GetMaxSerialNumber() int64 {
  b.NormalizeChapters()
  b.r.RLock()
  defer b.r.RUnlock()
  l := len(b.chapters)
  if l == 0 {
    return 0
  } else {
    return b.chapters[l-1].SerialNumber
  }
}


Did you do everything right? I will be grateful for any advice.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
M
montray, 2020-07-23
@vgrabkowot

Well, yes, it's okay. It will do.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question