4 ms·
I find it to always be either overused or underused. Either the app is a vanilla evented io web application, in which case you could write it in pretty much an
by phamilton 8y ago
I find it to always be either overused or underused.
Either the app is a vanilla evented io web application, in which case you could write it in pretty much any major language using an evented framework. Or it's a mess of buggy channel usage.
I guess there's a happy balance of "let the library maintainers do the hard channel work" but to be honest I can use someone else's high performance evented io library in any language.
- eikenberry 8y agoMy experiences doesn't reflect yours exactly, but I know what you mean. Go is still a fairly young language, so I think the patterns are still establishing themselves. But I think progress is being made and much of the code I've seen lately has been pretty good. Regarding libraries, best practice is to use CSP sparingly and to design the API as blocking calls so the applications have the choice of using the call directly or wrapping it with CSP.
- iainmerrick 8y agoWould it be fair to say it should be rare to see channels passed directly in the parameters or return types of a public API? If so, it feels to me like channels are a bit of a misfeature. They work OK as a way to implement concurrency, sure, but not in a way that you want to expose in your API. They’re not very composable. (That’s a bit hand-wavy as I’m not a heavy Go user. If there are good uses of channels in public APIs I’d be interested to hear about them.) Compare to e.g. maps, or closures. Those are very generally useful and composable primitives and it’s therefore common to see them used directly in APIs.
- eikenberry 8y ago> Would it be fair to say it should be rare to see channels passed directly in the parameters or return types of a public API? Yes, it is pretty rare. The only example I know off the top of my head is the ssh library, but I would say it is an appropriate and good use of them and you can look at that as a possible example. https://godoc.org/golang.org/x/crypto/ssh https://godoc.org/golang.org/x/crypto/ssh > If so, it feels to me like channels are a bit of a misfeature. They work OK as a way to implement concurrency, sure, but not in a way that you want to expose in your API. They’re not very composable. If you just look at channels and goroutines without some knowledge of CSP they will look a bit rough and low level, but once you understand CSP you'll see they are one of the better primitives available today. IMO the main problem with them is that people try to just use them without really understanding how to use them and it is pretty easy to shoot yourself in the foot with them.
- jerf 8y agoYes, officially, channels should be rarely seen in library APIs. This is because most of the time the library is doing something that should be simply done synchronously. If a consumer of your library wants to do something with that synchronous operation, it is up to them to use the concurrency tools to do so. You can't provide a library that is as flexible as what the language already offers, because you can't help but hard-code some aspect of what is going to be done. But there are rare cases where you may want to offer them. I find a pattern I often have is to officially provide a method or set of methods that do whatever the thing is, but if you have a sophisticated case where you may need the thing the library is doing to participate in a select, you can offer a channel. There's often additional responsibilities for the caller that come with it when I do that. But it's more efficient that asking them to spawn a brand new goroutine just to call my code that is just going to drain a channel for them. Some particularly advanced fixtures may even have their own internal plumbing bits, but you normally shouldn't care about those. Channels are fairly composible, it's just that it shouldn't be libraries doing the composing. To use a rough physical equivalent, your sink, dishwasher, toilet, and shower don't come with their own pipes to hook into the system, because whoever made those things have no idea what your local concerns will be. Fixtures are the library functionality, and the channels are the local plumbing. It's not a perfect metaphor, since physical objects intrinsically fix more aspects than code does, so don't pick at it too hard, it's just something to get an idea across. (They'll get more composable with the new generics stuff, when it comes out. Although possibly dangerously so; generic channel libraries are going to make it easy to compose yourself up some local plumbing that involves way too many hidden goroutines and channels and will make it easy to trash performance.)