Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

No good way, no.

I consider this a Go anti-pattern. Without a good reason, do not try to provide "asynchronousness" in a library. Go natively supports goroutines and channels, and it's considered baseline skill in the language to be able to fire something off in a goroutine (it's literally a two-character keyword) and receive something on a channel, if you want to. It would be not only adequate but preferable to implement this library as a fully synchronous request system and expect the user of the library to implement what asynchronousness they may require. Your hardwiring of exactly how the "asynchronousness" works may conflict with my own needs.

All the "asynchronousness" you need to provide is already hard-wired into the Go runtime itself; what certain language communities have trained you to think is "synchronous" code already isn't. You don't have to super-duper-extra make it even more asynchronous.

I won't quite call exposing channels in a library API a code smell, it's a little too useful for that, but it's still something where you ought to pause for a moment and really think about what it means, especially if you created it rather than receiving it.

Oh, and let me be clear: Levigross, I'm seriously suggesting that you change this library wholesale to be fully synchronous, and the fact that this will be an API change is a feature, not a bug. You'll find it also simplifies the API significantly, also a feature.



Jerf,

Thank you for the suggestion. I plan on adding some functionality to make asynchronous APIs friendlier to use (like a `Do` or `Apply` function etc...). But if you don't choose to use the asynchronous APIs everything still functions the same (in fact the asynchronous APIs use the synchronous functions and slap channels on them)


No, seriously, just remove your "asynchronous APIs". You don't need them. They aren't adding anything. Just remove them. Go already does all that.

Oh, what the heck, I'll name names. This is part of why I've been so pissy at the Node community for the past few years. Their definition of synchronous is wrong, and it's really become quite popular. Synchronous does not mean "blocks the whole process". That is a weakness of Node, not a universal programming truth. From the Node perspective, all Go code is always and automatically asynchronous. You don't have to add it. It already is. You're not adding functionality by trying to "nicely" provide an asynchronous API, you're simple redundantly adding what is already there, and what you're adding is significantly less flexible than what Go already provides.

(Now with more correct definitions of the terms, it is meaningful to say that Go code is synchronous within a goroutine. But Go already provides abundant tools for dealing with that within its runtime. We can already compose these tools together trivially to do whatever async patterns we want.)

Now, I suppose, standard disclaimer, this is your library, do as you like. I'm not actually personally passionate about this like I'm yelling at my monitor or anything. I'm trying to help you save time and effort. It's up to you what you decide to do.


Jerf,

1. Thank you for the feedback

As you have already seen, I submitted my library to /r/golang and have gotten a lot of feedback – from which I modified the constructs (originally the functions returned channels).

I want to write something that is useful to as many people as possible (all while not alienating anyone) and therefore try not to force users (like I originally did) to use the "asynchronous APIs".

I didn't expect this to end up on HN and was going to start a discussion on golang-nuts on the pros and cons of this construct. Based on that, I was going to remove or keep the APIs.


+1 for removal, YAGNI.


I definitely support this sentiment w/r/t the single threaded mindset of node and their async all the things approach. The only question with Go is if we guarantee sync libs, then where is the good async example code? I agree libraries should be synchronous, but does it really hurt to not have some best practices "how to do it async" in the docs? or should it be... in the code?

Kind of a meta question, but an interesting one.


The "good asynchronous" code in Golang is straight-line code that would be called "synchronous" in Node.

Part of the problem is that even as an attempt at a "non-synchronous" interface, this seems clumsy. It demand-creates new channels for requests. That doesn't seem right.


Whats wrong with "demand-creating" channels? The Go stdlib does it within their network library https://golang.org/src/net/singleflight.go#L67


Because you can't select on an arbitrary collection of channels.

It might make sense for a library to return a new channel for something you do once, or once per goroutine.

It doesn't make sense to use returned channels as a basis for async dispatch.


> all Go code is always and automatically asynchronous

wat?


I think that was an overstatement, but in the sense we're talking about with an HTTP request library, his overall point is true: Golang's runtime yields to other coroutines on I/O system calls. There usually† isn't much point in designing your own I/O scheduling system in Golang; you're almost always better off just forking off a zillion coroutines and letting them merge their results back across a single channel.

At least in 1.1, I couldn't write a fast port-scanner without doing my own scheduling, but that's a corner case.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: