Skip to content

Instantly share code, notes, and snippets.

@xialeistudio
Last active December 8, 2025 01:39
Show Gist options
  • Select an option

  • Save xialeistudio/e8d5830cd0fdbabe938ee96a4507cd26 to your computer and use it in GitHub Desktop.

Select an option

Save xialeistudio/e8d5830cd0fdbabe938ee96a4507cd26 to your computer and use it in GitHub Desktop.
go actor
package actor
import (
"context"
"sync"
"go.uber.org/zap"
)
var (
MailboxSize = 100
)
type Actor interface {
Receive(ctx context.Context, msg any)
OnStop(ctx context.Context)
}
type PID struct {
mailbox chan any
cancel context.CancelFunc
wg sync.WaitGroup
actor Actor
}
func Spawn(actor Actor) *PID {
mailbox := make(chan any, MailboxSize)
ctx, cancel := context.WithCancel(context.Background())
pid := &PID{
mailbox: mailbox,
cancel: cancel,
actor: actor,
}
pid.wg.Add(1)
go pid.loop(ctx)
return pid
}
func (p *PID) Stop() {
p.cancel()
p.actor.OnStop(context.Background())
p.wg.Wait()
close(p.mailbox)
}
func (p *PID) Send(msg any) bool {
select {
case p.mailbox <- msg:
return true
default:
zap.L().Warn("actor mailbox full, dropping message", zap.Any("message", msg))
return false
}
}
func (p *PID) loop(ctx context.Context) {
defer p.wg.Done()
for {
select {
case msg := <-p.mailbox:
p.actor.Receive(ctx, msg)
case <-ctx.Done():
return
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment