26 ms·
Go as an alternative to Node.js for Very Fast Servers
- jacobmarble 14y agoNode: Everyone knows JavaScript, there's a massive community, there are tons of libraries, and you get very good performance Go: No one knows this language, there's a small-but-growing community, there are enough libraries to get a lot done, and you get even better performance Java: They are paying me (money!) to write in this language
- deleted 14y ago[deleted]
- tristan_juricek 14y agoYes, but at what point does go transition from obscurity to PG's "python paradox"? http://www.paulgraham.com/pypar.html http://www.paulgraham.com/pypar.html It sure seems Scala's in this "python paradox" land now. My guess is that you need some startups make it big using Go to evangelize it. Google using it is interesting, but I'm not sure it makes it "cool". Though, I'm not sure Java was ever a language you could use as a skillset filter. Hm.
- SeanDav 14y agoPretty much anything Google does is cool. Probably same could be said about Amazon, Facebook et al. Depends a lot on your interpretation of "Cool" though.
- tristan_juricek 14y agoRight. I get more of the sense that Google is more "impressive" than "cool". If I were to use "Google's got it in production" I might be told something like "well they can pull this off" as if they have some unattainable smarts or something. Whereas a "cool" thing is more about just simply taking a risk. Come to think of it, that's kind of a funny definition. Oh well.
- mhd 14y agoI think a lot of the "coolness" factor of Go comes not from its parent company, but from some of its core developers, namely Rob Pike & Ken Thompson. That gives Go a serious Bell Labs/Unix/Plan 9 pedigree. I don't follow the mailing list anymore, so I don't know if it already led to the same "cargo cult" fanboyship that Plan 9 sometimes evokes, where a lot of the idiosyncratic opinions of its developers (e.g. "shared libraries are bad") are basically never questioned and repeated almost like holy scripture.
- pjmlp 14y agoYes!
- tristan_juricek 14y agoI tend to think of "coolness" as a kind of reason behind early adoption, more like "this thing as a large opportunity for catching on". I'm not 100% sure would make the argument that "Rob Pike and Ken Thompson made it". Instead, I'd say "it's in use at Google, and all of these other startups..." If 1 or 2 of those startups hit it big (e.g. Twitter or LinkedIn kind of big) that might have a bit more of an "Ooo" factor. Though I have said, "it's incredibly well thought out, look, Rob Pike and Ken Thompson know what they're doing". I don't sense this quite had the gravitas I was looking for yet. Hm.
- mattgreenrocks 14y agoThe mainstream always lags behind significantly in every aspect of life. If everyone's using it, then you have little competitive advantage using the technology. Go would be one of the first things I'd reach for if there's any chance server-side concurrency would be involved. The language is minimalistic and unsurprising to the extreme. A joy to program in and use.
- mseepgood 14y agoThe Go community on Reddit is already bigger than the Node community: http://www.reddit.com/r/golang http://www.reddit.com/r/golang (3730) http://www.reddit.com/r/node http://www.reddit.com/r/node (3581)
- Flow 14y agoAnd the Google+ Go community is growing fast and is already larger than the sub-reddit. https://plus.google.com/communities/114112804251407510571 https://plus.google.com/communities/114112804251407510571
- sigzero 14y agoYou do see a correlation right?
- thebigshane 14y agoI think he was referring to the whole JavaScript community. For comparison: http://www.reddit.com/r/javascript http://www.reddit.com/r/javascript (27,041)
- driverdan 14y agoI wouldn't consider subreddits a good way to gauge a tech community's size. Try IRC rooms and mailing lists.
- VeejayRampay 14y agoMore like: Anything web HAS to be Javascript (cause the calendar says 2013 but apparently it's 1970), no choice so oh well, we'll try Javascript on the server cause God knows using the same language everywhere is a good thing :/ Go: The language is in its infancy, growing at a slow pace for now, bears some promises that are yet to be confirmed. Java: For some reason people still hate the language even though it's the closest to being the most versatile language around (in every single aspect that makes a good language it ranks well against the others)
- jlgreco 14y ago> For some reason people still hate the language even though it's the closest to being the most versatile language around (in every single aspect that makes a good language it ranks well against the others) In every respect that a PHB may care about, perhaps. I think you should examine that "for some reason" more carefully before declaring that all reasons favor Java. Clearly there is something going on there, unless you think everyone who dislikes Java just suffered head trauma or something.
- danieldk 14y agoWell, I know lots of programmers who do like Java, you just don't see them that much on Hacker News. Reasons: - Availability of good IDEs. - Good dependency management and build infrastructure via Maven. - Quick and easy deployment via servlet containers. I am not a big Java fan, but having written quite much code, feature-wise there are not that many advantages of Go over Java. Package management in Go is nice for an early system, but will become a mess eventually, since there is no version management at all. Goroutines and Gochannels are nice for concurrency, but not all that great for parallelization. Java has generics, checked exceptions, and a good garbage collector via the JVM. I don't hold much hope for the development of Java the language, but the JVM is a great platform, with many interesting languages (Scala, Kotlin, Clojure), that attempt to solve problems that Go doesn't solve.
- jlgreco 14y agoYou and VeejayRampay seem to have misunderstood me. I'm not saying the language is all bad, or that the technology is crap, or that there are not programmers who love everything about it. I am saying that there are reasons that many people dislike Java; it isn't just some sort of blind prejudice. @VeejayRampay Considering the love Clojure gets on HN, I reject the notion that Java gets a bad rap due to historic shortcomings of the JVM or ecosystem. No, the language itself is disliked, not the tech. Its constructs and its idiomatic usage. Things that your standard PHB will find difficult to quantify. This is in stark contrast with how the JVM is perceived (from my perspective, it seems to be widely adored). I'm saying this as someone who currently makes their living programming in Java.
- burke 14y agoI've been using Go a lot lately. It's difficult to overstate just how much simpler it makes writing highly-concurrent server-type programs. Entire classes of bugs, issues, and puzzles just vanish.
- chimeracoder 14y agoI've been using Go a lot recently as well, and it's rapidly become my go-to language (no pun intended) for a lot of problems, even when concurrency is not involved. The biggest thing Go gives me is that it's really easy to manage code bases that grow organically - refactoring a project that grows from 50 LOC to 5000 LOC is almost painless in Go - no other language that I've seen has dealt with this aspect of code development so well.
- alec 14y agoWhat about Go makes it easy to manage and refactor large codebases? I don't do much Java, but whenever I've watched someone use Eclipse for refactoring, I question why I'm still using vim, because it is just magic and does everything for you.
- chimeracoder 14y agoI should probably write a blog post about this, because it's a combination of a number of things. Primarily, the compiler is incredibly strict and opinionated, so it's impossible to make certain small errors like assigning to lvalues that are never used, importing packages that are never used, etc. Secondarily, gofmt makes code very standardized and easy to skim. It takes Python's 'only one (obvious) way to do it' one or two steps further, by forcing everyone to to write their code the same way. This makes refactoring a lot easier because you don't need to read as much code each time in order to understand what's going on (or at least, you can mentally parse it much faster). Finally, the context-free grammar combined with a strong, static type system means that migrating code from an old (incompatible) version of Go to the most recent one can be done painlessly with the 'go fix' tool. This isn't your py2to3 tool - this accepts valid (old) Go code as input and reliably produces valid (up-to-date) Go code as the output. That last bit isn't actually used in refactoring manually, but I make note of it because very few languages give you anything close to this level of reliability with code modification, which speaks volumes about the design of the language's grammar.
- jgrahamc 14y agoWhile JavaScript drags the scars of its hasty standardization around with it, Go was designed very thoughtfully from the beginning, and as a result I find that it’s a pleasure to write. This is very true. Go is a pleasure to write. In fact, it's such a pleasure then when you hit something that wasn't really well designed it's horrid.
- papsosouid 14y agoCan I ask what language you are used to? I hear how nice go is as a language a lot, but coming from haskell, go is hideous in comparison.
- deleted 14y ago[deleted]
- chimeracoder 14y agoGo is going to look hideous to you because you're probably expecting functional things like list comprehensions (which Go doesn't have) and a very intricate type system allowing for things like generics (which Go doesn't have either). Go code will look a little less DRY to you as a result, which is a fair criticism, but it makes up for that by being incredibly opinionated (that's a good thing), being incredibly easy to prototype in, and being incredibly easy to refactor painlessly.
- papsosouid 14y ago>Go is going to look hideous to you because you're probably expecting functional things like list comprehensions Nah, list comprehensions are just syntactic sugar and not used much in haskell. Python seems to encourage their use a lot, but you hardly even see them in haskell code. >a very intricate type system allowing for things like generics (which Go doesn't have either). That is definitely one of the big problems, but I take issue with the characterization of that as needing "a very intricate type system". Parametric polymorphism is very simple, and has been a completely solved issue for a very long time. There is simply no excuse for a brand new language to be decades behind on something so easy to do right. >being incredibly easy to prototype in, and being incredibly easy to refactor painlessly. Those are actually two of the other big issues going from go to haskell. Go is harder to prototype in, and it is easy to add bugs when refactoring because the type system is so poor.
- SeanDav 14y agoThe fact that Node.js is being used in this equation says a lot about how much impact and penetration it has achieved in a rather short while. Personally I hope that Go does just as well, if not a lot better. I am a bit of a fan of both.
- weego 14y agoI think it says more about the bias of the writer, he seems to assume that Node would be the default choice and that something like erlang/scala/clojure/go would be alternatives. That may be true for someones sideline project.
- jff 14y agoIf he's a HN reader, he's probably assumed that Node is the default choice these days, based on the articles that come up.
- VeejayRampay 14y agoNot really no. It only says a lot about how much advertising has been done recently about the webscaling capabilities of Node (like it's anything special). I think people are starting to realize that as good as it is, it simply isn't the only way to achieve results like these (see Vert.x, Tornado and tons of other projects with comparable capabilities).
- jbert 14y agoI played around with a go server to do some simple scaling numbers - looking at possibly using go to implement a large-number-of-idle-connections notification server. I found the (good) result that I could spawn a new goroutine for each incoming connection with minimal (~4k) overhead. This is pretty much what you'd expect since a goro just needs a page for it's stack if it's doing no real work. I had something like 4 VMs each making ~30k conns (from one process) to the central go server with something like 120k conns. I found one worrying oddity however. Resource usage would spike up on the server when I shut down my client connections (e.g. ctrl-C of a client proc with ~30k conns). Reasoning about things a bit, I think this is due to the go runtime allocating an OS thread for each goro as it goes through the socket close() blocking call. I think it has to do this to maintain concurrency. So I end up with hundreds of OS threads (each only lives long enough to close(), but I'm doing a lot at the same time). Can anyone comment: - is this guess as to the problem likely to be correct? - is this "thundering herd" a problem in practice? - are there ways to avoid this? (Other than not using a goro-per-connection, which I think it the only idiomatic way to do it?) My situation was artificial, but I could well imagine a case that losing, say a reverse proxy, could cause a large number of connections to suddenly want to close() and it would be a shame if that overwhelmed the server.
- aaronblohowiak 14y ago> I think this is due to the go runtime allocating an OS thread for each goro as it goes through the socket close() blocking call. I think it has to do this to maintain concurrency I highly doubt that it is creating a thread per goro on client disconnect. If you have a minimalish example of this, the golang mailing list would be very interested in working with you to identify what went wrong and create a patch if it is an issue with the Go implementation.
- evmar 14y agoIn case you didn't see it, I commented above with a link to a bug.
- tptacek 14y agoBlocking system calls spawn OS threads in Go, which can be cached and recycled for new goroutines. You don't see this if you code to pkg/net because it multiplexes i/o with a select/kqueue goroutine, but you'll see it right away if you code directly to the syscalls. Close isn't a blocking call, though.
- dpweb 14y agoI run node/express for most of my web servers and each takes up about 10-15mb RAM. They're very basic no fluff. Anyone know what comparable mem footprint in Go?
- codygman 14y agoHere's a quick paste from a server of mine: ps aux | grep api ubuntu 15720 0.0 0.1 107024 6136 pts/0 Sl 15:13 0:00 bin/api_server
- jff 14y agoIIRC ps displays the resident size in KiB, so you're looking at 6 MB for a Go process. Not terrible for a high-level language.
- codygman 14y agoYep, just ran ps_mem.py (http://www.pixelbeat.org/scripts/ps_mem.py http://www.pixelbeat.org/scripts/ps_mem.py) and here's my entire server. Not a busy one, but it lets you see what a running api server and accompanying programs look like. Private + Shared = RAM used Program 184.0 KiB + 31.5 KiB = 215.5 KiB atd 240.0 KiB + 55.0 KiB = 295.0 KiB cron 240.0 KiB + 68.0 KiB = 308.0 KiB upstart-socket-bridge 304.0 KiB + 72.0 KiB = 376.0 KiB upstart-udev-bridge 392.0 KiB + 79.0 KiB = 471.0 KiB sudo 696.0 KiB + 26.0 KiB = 722.0 KiB dhclient3 604.0 KiB + 189.0 KiB = 793.0 KiB getty (6) 940.0 KiB + 49.0 KiB = 989.0 KiB dbus-daemon 660.0 KiB + 366.0 KiB = 1.0 MiB udevd (3) 1.0 MiB + 71.0 KiB = 1.0 MiB rsyslogd 1.1 MiB + 35.5 KiB = 1.1 MiB redis-server 1.0 MiB + 122.5 KiB = 1.2 MiB init 964.0 KiB + 733.0 KiB = 1.7 MiB polkitd 1.4 MiB + 823.5 KiB = 2.2 MiB console-kit-daemon 2.5 MiB + 1.1 MiB = 3.6 MiB nginx (5) 1.3 MiB + 3.2 MiB = 4.6 MiB sshd (5) 5.4 MiB + 75.5 KiB = 5.5 MiB api_server <==== Go Program 13.8 MiB + 963.0 KiB = 14.7 MiB bash (2) 22.5 MiB + 314.0 KiB = 22.8 MiB mysqld 41.9 MiB + 5.1 MiB = 47.0 MiB python2.7 (2) 79.4 MiB + 542.0 KiB = 79.9 MiB java --------------------------------- 190.3 MiB =================================
- hrwl 14y agoI have never understood the focus on speed as a selling point for Node. It may well be very fast, but it seems to me that the primary selling points would be the ability to share code between client and server and that you can start coding server side without learning a new language if all you know is JavaScript.
- pcwalton 14y agoCompared to Python and Ruby, node.js is quite fast by the simple virtue of having a JIT (in the most common implementation anyway; of course there are JITs for Python and Ruby but they aren't the mainline implementation).
- codygman 14y agoWhich is a shame, since PyPy is really an excellent project.
- ebiester 14y agoI never thought of it as "faster-than-thou" but rather "faster than you expect" and "fast enough for real work."
- saidajigumi 14y agoFirst off, while some sharing between client and server happens, that tends to be an edge case in my experience. The roles of client and server, and APIs available to each, are rather different. I.e. the environment of the browser and node.js server aren't homogenous. Second, "start coding in XXX without learning a new language" is a terrible selling point. I've seen this thinking appeal to misguided PHB-types and witnessed the result: immense organizational damage. In my experience, this isn't a necessary or sufficient selling point to good developers. Learning a new language just isn't that hard, and a big part of a shift like this is actually in learning the new environment's paradigms, APIs, and best practices. To make the latter point more strongly: if you're having doubts about your ability to pick up a new language, definitely take some time to learn a few new languages. Do a tutorial, play with a few small projects, enough to get the flavor of the language. Your hackery will benefit immensely from this, even when you return to your primary language.
- deleted 14y ago[deleted]
- chimeracoder 14y ago> Shouldn't that be "Go-lang" because we all agreed to call it Golang? I might be missing something. I'm the one missing something, because I'm not sure who 'we' are, or when 'we' all supposedly agreed to this. In any case, you should probably inform the authors of the spec, because they apparently missed this memo too[0]! [0] http://golang.org/ref/spec http://golang.org/ref/spec
- stcredzero 14y ago> There’s no arguing about whether to use semicolons, or putting your commas at the front of the line — the language knows what it wants. It’s a built-in hipster suppression mechanism. Major point for saving man hours right there.
- islon 14y agoClojure is another nice alternative for fast servers, and using a concurrent, immutable and functional language is a huge win. http-kit is a good example of such server: http://http-kit.org/ http://http-kit.org/
- mjijackson 14y agoI was curious, so I actually ran both of the servers from the article on my little MacBook Air. The results are below. First, go: $ ab -c 100 -n 10000 http://localhost:8000/ This is ApacheBench, Version 2.3 <$Revision: 655654 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/ Benchmarking localhost (be patient) Completed 1000 requests Completed 2000 requests Completed 3000 requests Completed 4000 requests Completed 5000 requests Completed 6000 requests Completed 7000 requests Completed 8000 requests Completed 9000 requests Completed 10000 requests Finished 10000 requests Server Software: Server Hostname: localhost Server Port: 8000 Document Path: / Document Length: 1048576 bytes Concurrency Level: 100 Time taken for tests: 10.085 seconds Complete requests: 10000 Failed requests: 0 Write errors: 0 Total transferred: 10489017384 bytes HTML transferred: 10487857152 bytes Requests per second: 991.62 [#/sec] (mean) Time per request: 100.846 [ms] (mean) Time per request: 1.008 [ms] (mean, across all concurrent requests) Transfer rate: 1015729.90 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 1 2 0.8 2 6 Processing: 21 99 5.6 98 137 Waiting: 1 3 2.7 2 41 Total: 25 101 5.6 101 139 Percentage of the requests served within a certain time (ms) 50% 101 66% 102 75% 103 80% 103 90% 105 95% 106 98% 108 99% 112 100% 139 (longest request) Secondly, node.js: $ ab -c 100 -n 10000 http://localhost:8000/ This is ApacheBench, Version 2.3 <$Revision: 655654 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/ Benchmarking localhost (be patient) Completed 1000 requests Completed 2000 requests Completed 3000 requests Completed 4000 requests Completed 5000 requests Completed 6000 requests Completed 7000 requests Completed 8000 requests Completed 9000 requests Completed 10000 requests Finished 10000 requests Server Software: Server Hostname: localhost Server Port: 8000 Document Path: / Document Length: 1048576 bytes Concurrency Level: 100 Time taken for tests: 15.765 seconds Complete requests: 10000 Failed requests: 0 Write errors: 0 Total transferred: 10487558651 bytes HTML transferred: 10486808576 bytes Requests per second: 634.31 [#/sec] (mean) Time per request: 157.653 [ms] (mean) Time per request: 1.577 [ms] (mean, across all concurrent requests) Transfer rate: 649639.92 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 1 1.7 1 11 Processing: 2 156 34.7 159 272 Waiting: 1 47 29.7 42 136 Total: 2 157 34.7 161 273 Percentage of the requests served within a certain time (ms) 50% 161 66% 174 75% 182 80% 187 90% 198 95% 209 98% 221 99% 227 100% 273 (longest request) Not only does go serve the traffic more quickly, but it also has a much lower standard deviation between slow and long requests. Impressive.
- btown 14y ago> The biggest promise that Node makes is the ability to handle many many concurrent requests. How it does so relies entirely on a community contract: every action must be non-blocking. All code must use callbacks for any I/O handling, and one stinker can make the whole thing fall apart. Try as I might, I just can’t view a best practice as a feature. Nonblocking I/O isn't just a "best practice" in the sense that consistent indentation is a "best practice," it's a core tenet of the Node ecosystem. Sure, you could write a Haskell library by putting everything in mutable-state monad blocks, and porting over your procedural code line-for-line. It's allowed by the language, just like blocking is allowed by Node. But the whole point of Haskell is to optimize the function-composition use case. The Node community has the benefit of designing all its libraries from scratch with this tenet in mind, so in practice you never/rarely need to look for "stinkers" unless they're documented to be blocking. And unless they're using badly-written blocking native code, you can just grep for `Sync` to see any blocking calls.
- tferris 14y agoHow long does take the compile time with a medium sized typical web project. Something which gets annoying or still bearable?
- icey 14y agoI am working on a project that has a few thousand lines of Go and compilation takes a second or so. Maybe less; it's fast enough that I don't really think about the fact that it's compiling unless I've done something that it complains about (which is awesome).
- grey-area 14y agoIf you mean go, compile time is very fast, even with say 10 kloc you'll still probably be under a second.
- WhaleFood 14y agoOne advantage of node that wasn't mentioned is the ability to share server side and client side code. Avoiding discrepancies in the same form validation written in two different languages can often be more important than performance gains in server applications.
- papsosouid 14y ago>One advantage of node that wasn't mentioned is the ability to share server side and client side code You can do that with lots of languages, using one of the langX->javascript compilers. >Avoiding discrepancies in the same form validation written in two different languages What form validation are you doing in javascript? I can't actually think of any client side validation that isn't just a regex.
- deleted 14y ago[deleted]
- stesch 14y agoWhat do you use for persistence? I know what's available, but which database and library could be recommended for a low to medium traffic web site?
- jamwt 14y agoHere's a haskell comparison (hint: it does very well). https://gist.github.com/jamwt/5017172 https://gist.github.com/jamwt/5017172 Haskell was ghc 7.6.1 with ghc --make -O2 Go is go1.0.2 with "go build".
- gnuvince 14y agoWarp is very nice.
- e12e 14y agoAs noted above - with ridiculously large values for ab this one crashes (although I didn't compile with O-parameters). I think this (and the other haskell solution) ran out of resources. Both the go and nodejs versions completed without problems. I was a little disappointed -- I was actually hoping I'd see comparable performance -- even if it is a silly test. I think it is interesting that simple, idomatic code in go and nodejs didn't crash -- not sure what assumptions might be "wrong" in the underlying haskell code (I'm guessing if anything should be "fixed" it is in the web server libraries used).
- babuskov 14y agoIs there a socket.io equivalent for Go? In terms of ease of use and at least providing the same functionality.
- mfenniak 14y agoLooks like there are a couple packages that would solve this problem, but neither appear to be production ready or up-to-date. https://github.com/madari/go-socket.io https://github.com/madari/go-socket.io https://github.com/igm/sockjs-go/ https://github.com/igm/sockjs-go/
- deleted 14y ago[deleted]
- tferris 14y agoI find this post paired with this thread confusing. Yes, Go is tempting and I'd like to try it since a lot of people get quickly into flow with Go, the "package manager is so great" and "everything is just a breath of fresh air". But what I don't like: the negativity against Node and omitting some facts. In the replies of the orignal post a guy tested two (!) times Node and once it was significantly faster (v0.6) and once it had same speed (v8.0). So, why has mjijackson such different results in this thread at the top?? And maybe we should test it on real servers and not on a MBA. Moreover, we have here some micro benchmark which possibly doesn't reflect reality well. Don't get me wrong, I appreciate any benchmarking between languages but then please do it right and make no propaganda out of it. Further, Go's package manager seems to be nice but it does NOT have version control. How do you want to use this in a serious production environment. Maybe version control will come (but then tell how without loosing its flexibility) or not but this is something serious and definitely not an alternative to any server environment except for some mini services. EDIT: downvoting is silly, propaganda and won't help the Go community in getting more credibility, better do some further benchmarks; otherwise this post/thread is full of distinct misinformation and should be closed
- cmccabe 14y agoGo's package manager does have version control. It looks for specially named branches (different ones depending on the version of go you have). The upstream authors can provide a different version of the software for different releases of Go. If you want to lock down the versions of all the software you're deploying in your organization, that's easy to do too. Just "git clone" all of the libraries you use to some internal server (and/or github repos), and change the URLs to point to that server. You control when everything gets updated. Golang builds static binaries anyway. So if you test a binary and it works, you just copy it to all the servers you care about and you're done. If you're in a small and informal shop, maybe you don't need to mirror every repository. Due to the nature of git, if the upstream repo ever gets deleted, you can fall back on a local copy of it anyway. This is all very much in contrast to languages like Java where keeping around the proper version of every jar and carefully deploying that version (and only that version!) on each server is big deal (and despite OSGI, still very much an unsolved problem.)
- eduran 14y agoI thought GO was dead... just like googlevideos and igoogle...
- logn 14y agoI wonder how Go compares to SilkJS, since SilkJS is much faster than Node.
- robert-zaremba 14y agoSilkJS uses mostly the same libraries and relay on the same VM as Node.js: V8. So it can't be much faster. The note how it outperform Node.js http server, you can read from start page of its github repository, are misleading since it uses multiple processes (SilkJS http server forks itself).
- dgudkov 14y ago>There are also some officially maintained repositories outside of the stdlib that deal with newer protocols like websockets and SPDY. Does anybody from HNers use Go with websockets? What package do you use?