About the memo in gopl chapter 9

original code:

Hello, I think it will be faster if I change the Get method to:

func (memo *Memo) Get(key string) (interface{}, error) {
	e := memo.cache[key]
	if e != nil {
		<-e.ready
		return e.res.value, e.res.err
	}

	memo.mu.Lock()
	e = memo.cache[key]
	if e == nil {
		e = &entry{ready: make(chan struct{})}
		memo.cache[key] = e
		memo.mu.Unlock()
		e.res.value, e.res.err = memo.f(key)
		close(e.ready)
	} else {
		memo.mu.Unlock()
		<-e.ready
	}
	return e.res.value, e.res.err
}

Because there will be less locks from memo.mu.Lock().

What do you think? Dose my change has effect?

Thanks.

m := New(httpGetBody)
	var n sync.WaitGroup
	for i := 0; i < 50000; i++ {
		n.Add(1)
		go func() {
			defer n.Done()
			i := i
			key := strconv.Itoa(i % 1000)
			 _, err := m.Get(key)
			if err != nil {
				log.Println(err)
			}
		}()
	}
	n.Wait()

I got this error:
fatal error: concurrent map read and map write

It seems that:

for map[string]*entry, concurrent read + write is not allowed

Correct. You could try a sync.Map. The documentation says it’s “specialized” so it might end up making it worse, so, as always, benchmark it to see if it works better for you.