Goroutines, channels, and sync patterns for concurrent programming. Use when implementing concurrent operations.
/plugin marketplace add IvanTorresEdge/molcajete.ai/plugin install ivantorresedge-go-tech-stacks-go@IvanTorresEdge/molcajete.aiThis skill inherits all available tools. When active, it can use any tool Claude has access to.
Go concurrency patterns using goroutines, channels, and synchronization primitives.
Use this skill when:
// Start a goroutine
go func() {
fmt.Println("Hello from goroutine")
}()
// With parameters
go processItem(item)
// Anonymous function with closure
for _, item := range items {
item := item // capture range variable
go func() {
process(item)
}()
}
func worker(ctx context.Context) {
for {
select {
case <-ctx.Done():
return
default:
doWork()
}
}
}
ctx, cancel := context.WithCancel(context.Background())
go worker(ctx)
// Later...
cancel() // stop the worker
// Unbuffered channel
ch := make(chan int)
// Buffered channel
ch := make(chan int, 10)
// Send
ch <- 42
// Receive
value := <-ch
// Receive with ok
value, ok := <-ch
if !ok {
// channel closed
}
// Close
close(ch)
func fanOut(input <-chan int, workers int) []<-chan int {
channels := make([]<-chan int, workers)
for i := 0; i < workers; i++ {
channels[i] = worker(input)
}
return channels
}
func fanIn(channels ...<-chan int) <-chan int {
out := make(chan int)
var wg sync.WaitGroup
for _, ch := range channels {
wg.Add(1)
go func(c <-chan int) {
defer wg.Done()
for v := range c {
out <- v
}
}(ch)
}
go func() {
wg.Wait()
close(out)
}()
return out
}
func generator(nums ...int) <-chan int {
out := make(chan int)
go func() {
defer close(out)
for _, n := range nums {
out <- n
}
}()
return out
}
func square(in <-chan int) <-chan int {
out := make(chan int)
go func() {
defer close(out)
for n := range in {
out <- n * n
}
}()
return out
}
// Usage
nums := generator(1, 2, 3, 4)
squares := square(nums)
for v := range squares {
fmt.Println(v)
}
func workerPool(ctx context.Context, jobs <-chan Job, results chan<- Result, numWorkers int) {
var wg sync.WaitGroup
for i := 0; i < numWorkers; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for {
select {
case <-ctx.Done():
return
case job, ok := <-jobs:
if !ok {
return
}
result := processJob(job)
select {
case results <- result:
case <-ctx.Done():
return
}
}
}
}()
}
wg.Wait()
close(results)
}
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
process(id)
}(i)
}
wg.Wait() // wait for all goroutines
type SafeCounter struct {
mu sync.Mutex
count int
}
func (c *SafeCounter) Inc() {
c.mu.Lock()
defer c.mu.Unlock()
c.count++
}
func (c *SafeCounter) Value() int {
c.mu.Lock()
defer c.mu.Unlock()
return c.count
}
type Cache struct {
mu sync.RWMutex
items map[string]*Item
}
func (c *Cache) Get(key string) *Item {
c.mu.RLock()
defer c.mu.RUnlock()
return c.items[key]
}
func (c *Cache) Set(key string, item *Item) {
c.mu.Lock()
defer c.mu.Unlock()
c.items[key] = item
}
var (
instance *Singleton
once sync.Once
)
func GetInstance() *Singleton {
once.Do(func() {
instance = &Singleton{}
})
return instance
}
import "golang.org/x/sync/errgroup"
func processParallel(ctx context.Context, items []Item) error {
g, ctx := errgroup.WithContext(ctx)
for _, item := range items {
item := item // capture
g.Go(func() error {
return processItem(ctx, item)
})
}
return g.Wait() // returns first error
}
func handleRequests(ctx context.Context, requests <-chan Request, timeout time.Duration) {
for {
select {
case <-ctx.Done():
return
case req := <-requests:
processRequest(req)
case <-time.After(timeout):
log.Println("timeout")
}
}
}
// Good - can be stopped
func worker(ctx context.Context) {
ticker := time.NewTicker(time.Second)
defer ticker.Stop()
for {
select {
case <-ctx.Done():
return // exit path
case <-ticker.C:
doWork()
}
}
}
// Bad - goroutine leak
func worker() {
ticker := time.NewTicker(time.Second)
for range ticker.C {
doWork() // no way to stop
}
}
func generator(done <-chan struct{}) <-chan int {
out := make(chan int)
go func() {
defer close(out)
for i := 0; ; i++ {
select {
case out <- i:
case <-done:
return
}
}
}()
return out
}
value, ok := <-ch// Bad
for _, item := range items {
go func() {
process(item) // wrong item!
}()
}
// Good
for _, item := range items {
item := item // capture
go func() {
process(item)
}()
}
// Bad - leaks goroutine
func leak() {
ch := make(chan int)
go func() {
ch <- 1 // blocks forever if no receiver
}()
}
// Good - can complete
func noLeak() {
ch := make(chan int, 1) // buffered
go func() {
ch <- 1 // won't block
}()
}
// Bad - data race
var counter int
for i := 0; i < 10; i++ {
go func() {
counter++ // race!
}()
}
// Good - synchronized
var mu sync.Mutex
var counter int
for i := 0; i < 10; i++ {
go func() {
mu.Lock()
counter++
mu.Unlock()
}()
}
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.