3 ms·
> The actual core of OTP was the supervisor tree but that's too complicated so Golang is basically just more concise Java. Which is ironic, maybe kinda funny.
by rollcat 1y ago
> The actual core of OTP was the supervisor tree but that's too complicated so Golang is basically just more concise Java.
Which is ironic, maybe kinda funny. The first "larger" project I've tackled in Go was a chat server. I wanted a simple supervisor for each connected client; in case a goroutine encountered a recoverable error but needed to be restarted. I don't have any practical experience with OTP, but I've always been a big fan of daemontools/runit/etc: just let it crash, restart, and recover.
So in Go, you can't (easily) obtain a handle to a goroutine. The authors' entire argument seemed to be that this would allow developers to implement "bad" patterns, like thread-local storage. You can of course still come up with some wrapper code, like this:
type Service struct {
err <-chan error
run func(*Service)
}
s := &Service{err: make(chan error)}
realRun := func() error { ... }
s.run = func(s *Service) {
s.err <- realRun()
}
go s.run(s)
err := <-s.err
But what you really wanted was something like:
run := func() error { ... }
g := go run()
err := <-g
Now of course you still want some wrapper code to maintain client/connection state, etc. But if you wanted a "real" supervisor tree, you'd have to do this dance for every sub-goroutine you'd like to spawn. You'll soon end up with func(*Service, any) and throw away static typing along the way. Generics wouldn't be introduced until 18 releases after, and I don't think they would help all that much.
Correct me if I'm missing anything obvious.