저는 가능한 많은 수의 맵 엔트리를 범위를 지정하여 채널로 보내야하는 시나리오가 있습니다. 채널의 다른 끝에서의 작업은 오랜 시간이 걸릴 수 있으며지도는 동시에 액세스됩니다 (RWMutex
으로 보호). 지도는 다소 크기가 커서 임시 사본을 만들지 않으려합니다. 동시에지도 엔트리를 채널로 읽어들입니다.
type Example struct {
sync.RWMutex
m map[string]struct{}
}
지금 나는 이런 식으로 뭔가를 내놓았다 :
내가이 같은 구조체가 있다고 가정
:func (e *Example) StreamAll() <-chan string { toReturn := make(chan string) go func() { e.RLock() defer e.RUnlock() for k := range e.m { e.RUnlock() toReturn <- k e.RLock() } close(toReturn) }() return toReturn }
language specification는지도를 통해 이르기까지에 대한 흥미로운 비트가 있습니다
아직 도달하지 않은 맵 항목이 반복 중에 제거되면 해당 반복 값은 제거되지 않습니다. 생산 될 수있다. 반복되는 동안 맵 항목이 작성되면 해당 항목이 반복 중에 생성되거나 건너 뛸 수 있습니다.
자, 내가 알고 싶은 것은 이것입니다 : 반복마다지도가 변경 되더라도지도 위에 올리는 방법이 작동한다는 보장이 있습니까? 마지막으로 읽은 키가 삭제 된 경우 포함? 나는 모든지도 엔트리가 필요하지 않지만 그 중 대부분은 필요합니다. 당신이 키를 생성으로지도가 변화하고, 당신이 얻을 수 있도록 : 이것은 당신이 무엇을
0) 일관성 스냅 샷 :
package main
import (
"fmt"
"sync"
)
type Example struct {
sync.RWMutex
m map[string]struct{}
}
func NewExample() *Example {
return &Example{
m: make(map[string]struct{}),
}
}
func (e *Example) Put(s string) {
e.Lock()
defer e.Unlock()
e.m[s] = struct{}{}
}
func (e *Example) Delete(s string) {
e.Lock()
defer e.Unlock()
delete(e.m, s)
}
func (e *Example) StreamAll() <-chan string {
toReturn := make(chan string)
go func() {
e.RLock()
defer e.RUnlock()
for k := range e.m {
e.RUnlock()
toReturn <- k
e.RLock()
}
close(toReturn)
}()
return toReturn
}
func main() {
e := NewExample()
e.Put("a")
e.Put("b")
values := e.StreamAll()
// Assume other goroutines concurrently call Put and Delete on e
for k := range values {
fmt.Println(k)
}
}
놀이터에 대한 링크가 작동하지 않습니다. – OneOfOne
감사합니다. 지금 질문에 답했습니다. – mrd0ll4r
'range' 액션 자체는 동시에 안전하게 수행되어야하며 맵이 변경되면 이상한 요소 시퀀스가 생길 수 있습니다 (맵의 범위를 지정할 때마다 얻을 수있는 요소의 순서는 –