Instead of using `chan struct{}` everywhere, you could `type KillChan chan struct{}` so that you can just say `KillChan` (or whatever you want). This has the positive of still being able to use variables of type KillChan in selects/recvs/sends/etc.
You could even give KillChan the methods "Check" and "Kill" to do the select or the sending of the kill signal if you didn't want to leak your implementation into code that uses it.
Also, when doing kill signals it is customary to close the chan rather than send the `struct{}{}` if you don't plan on reusing the channel anyway.
I also believe that you may have made your "cut" method a little to generic: you wrote code that supports cutting the slice in any arbitrary location. This is good, but then you never actually use it to do anything but slice off the right side of the slice and keep everything on the left intact. I would personally remove the cut method entirely and just do the task of copying the right side of the slice into a new slice to return and shortening the slice saved in the List. It simplifies your code to what it is (a stack).
Also, how do you plan on passing work for these workers? I suppose you code receive on a `chan func()` that is shared among all workers in the select with the kill signal.
How many goroutines do you have at max? Goroutines are not that
expensive. So if you have a hundred of idle goroutines, you can just
preserve them till next spike.
--
--
Of course! Much simpler indeed.
http://play.golang.org/p/pBPYsDQ8VT
But more vulnerable to misbehaving workers too.
May be you'd better implement an approach used by
database/sql.DB [1] which is actually a pool of connections so that
when a new one is requested, either a pooled one is returned or a new
created? You could then separately manage a number of goroutines to
keep around and a number of connections to cache.
http://golang.org/pkg/database/sql/#DB
Isn't beanstalkd communication far more expensive than
creating a goroutine or channel comm. within a Go program? Why
not have one set of goroutines to pull off work and then fork
off worker goroutines each with the work request and a chan
back to the puller (which communicates on its behalf over the
beankstalkd conn). You can only have one process safely
read/write on a tcp connection (no guarantee that writes from
two proceces on the same fd will be atomically done) hence the
indirection. But you can do the actual work in prallel. The
puller goroutines can self-adjust their number based on load.
temp := make([]Worker, count)
for i := range temp {
temp[i] = make(Worker, 1)
}