install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/go-sync-primitives" ~/.claude/skills/majiayu000-claude-skill-registry-go-sync-primitives && rm -rf "$T"
manifest:
skills/data/go-sync-primitives/SKILL.mdsource content
Sync Primitives
sync.WaitGroup - Wait for Goroutines
CORRECT
func processBatch(items []string) { var wg sync.WaitGroup for _, item := range items { wg.Add(1) // BEFORE launching goroutine go func(item string) { defer wg.Done() process(item) }(item) } wg.Wait() // Block until all done }
WRONG - Add inside goroutine
func processBatch(items []string) { var wg sync.WaitGroup for _, item := range items { go func(item string) { wg.Add(1) // WRONG: race condition defer wg.Done() process(item) }(item) } wg.Wait() // May return early }
WRONG - Missing variable capture
func processBatch(items []string) { var wg sync.WaitGroup for _, item := range items { wg.Add(1) go func() { defer wg.Done() process(item) // WRONG: captures loop variable }() } wg.Wait() }
sync.Mutex - Protect Shared State
CORRECT
type Counter struct { mu sync.Mutex value int } func (c *Counter) Increment() { c.mu.Lock() defer c.mu.Unlock() c.value++ } func (c *Counter) Value() int { c.mu.Lock() defer c.mu.Unlock() return c.value }
WRONG - Unlocked access
type Counter struct { mu sync.Mutex value int } func (c *Counter) Increment() { c.mu.Lock() c.value++ // What if panic happens? c.mu.Unlock() } func (c *Counter) Value() int { return c.value // WRONG: race condition }
sync.RWMutex - Multiple Readers
type Cache struct { mu sync.RWMutex data map[string]string } func (c *Cache) Get(key string) (string, bool) { c.mu.RLock() // Multiple readers OK defer c.mu.RUnlock() val, ok := c.data[key] return val, ok } func (c *Cache) Set(key, value string) { c.mu.Lock() // Exclusive writer defer c.mu.Unlock() c.data[key] = value }
Rules
WaitGroup
- Call
beforeAdd()
statementgo - Always use
defer wg.Done() - Pass loop variables as function parameters
- One
can count multiple goroutinesAdd(n)
Mutex
- Always use
defer mu.Unlock() - Keep critical sections small
- Don't hold locks during I/O or slow operations
- Use RWMutex for read-heavy workloads
- Never copy a mutex (pass by pointer)
sync.Once - Run Exactly Once
var ( instance *Singleton once sync.Once ) func GetInstance() *Singleton { once.Do(func() { instance = &Singleton{} }) return instance }
Race Detection
go test -race ./... go run -race main.go