- What is Go well suited for other than network programming? - Why might one decide to write the backend API of their web app in Go, compared to say Grails, Python etc.
Moreover, I love static deploys and cross compilation with Go. Compile your app (even to Windows!), copy it to a server, simply run it as a single binary. No dependency management, no apt-get & easy_install & pip, it just runs.
For instance, look at the "Go Concurrency Patterns: Pipelines and cancellation" article: https://blog.golang.org/pipelines You'll notice the line "We introduce a new function, merge, to fan in the results" and after that, you will see how you have to write merge() yourself for every different data type that you use. Yes, you will have to repeat this same type of code, over and over, any time you want to pipeline, fanout, or merge, a new data type (unless you resort to interface{}). Furthermore, you will have to use the Go race detector to make sure you didn't actually mess something up.
I can't speak for Python or Ruby, but if you are using Node.js you can use a library like Bluebird which provides promise combinators. Then it's very easy to perform 5 requests and to handle errors and cancellation on one or more requests. You can do this and more on any arbitrary data type without writing merge() and nesting coroutine returning functions repeatedly.
So for handling async operations like dealing with APIs, I personally prefer tools like promise combinators or reactive programming (see Reactive Extensions for Javascript, also available in many other languages, or supplies in Perl 6 if you're crazy like me) over the significantly more manual approach of using typed channels in Go. I'm sure there are tasks where tight manual control of channels is important, but for the type of work I've been doing Go is simply too low level.
This article goes into more detail on the weaknesses of pipelining in Go: https://gist.github.com/kachayev/21e7fe149bc5ae0bd878
This example is terrible. Waiting for DB responses, ElasticSearch queries, and long running IO is one place where Python and Ruby multi-threading with a GIL works great. A GIL means multiple threads can't execute Python code at the same time. All of those tasks are by definition NOT running Python code, they're sitting around blocked waiting for responses.
A better example would be something like image processing, where an image is loaded into memory, broken into multiple independent chunks, and each chunk is processed at the same time in multiple threads. In Go that should work just fine, but in Python and Ruby each thread will spend a lot of time waiting for the GIL.
I am aware that other languages perform better in benchmarks than, say, Python does. But in my experience, I've not ever found the speed of the language to be a bottleneck when I'm benchmarking and optimizing for scalability in a web app.
It's always something else. The database interface, the network, a crappy web framework, whatever. It always seems to be something other than the fundamental language that bogs things down.
I'll openly admit I might be missing something or that perhaps I haven't tried to scale high enough. I just don't get how it's relevant that x language is y times faster than Python when Python hasn't ever been the problem. There's always just so much more low-hanging fruit than the language.
Actually that example does tend to be simple and readable in Python and Ruby. I've used a pattern similar to this to parallelize calls to a few back-end services from a Ruby app and it worked out great. The code I used looked something like this: https://gist.github.com/kevinmcconnell/8365521, which I think is quire readable.
I've definitely found Go's approach to concurrency to be very helpful in other situations; I just think that example could be a bit misleading.
As others have noted, the example use case is one where multithreading with a GIL/GVL isn't particularly problematic. Moreover, both Python and Ruby have GIL/GVL-free implementations (in Python's case, Python 2 only in Jython/IronPython; in Ruby's case, much more current in the language level supported, since current JRuby is Ruby 2.2-compatible.)
FWIW, you can use a ruby gem like typhoeus specifically for this:
hydra = Typhoeus::Hydra.new
requests = (0..9).map{ Typhoeus::Request.new("www.example.com") }
requests.each{ |request| hydra.queue(request) }
# blocks until all requests are complete
hydra.runWith Go (as compared to Python), it's super easy to define some structs, serialize and deserialize them as JSON that you check, and send them to the client quickly and efficiently.
The more annoying question for web apps (and productivity in general) is the static (+-strong) vs dynamic (+-weak) typing. Go, like Scala, does a great job inferring types (IMO) letting you feel fairly productive, but some people will always yearn for the "anything goes" dynamism (sadly combined with the lack of compile-time checking that would save you on larger projects).
Go was designed with this in mind and some of its shortcomings come from this approach. It is a relatively small language, with one way of doing a certain thing and a mandate of using standard libraries and strict code formatting.
It sounds limiting but it is productive and makes every Go developer write in the same style.
So whether it is you that you return to your project after a few months or a new developer, you will be able to (re)engage with the code quickly.
You'll get a lot of different opinions on this. I'll just speak based on my experience, since Python was my primary language before coming to Go.
Everything I used to use Python for, I can do faster in Go. The notable exception to this is statistical analysis, as Go does not have any FORTRAN bindings[0], whereas Python does (through Numpy & co.). I still use a combination of Python, R, and other languages for this.
I came to Go for the static typing and native concurrency[1], but I stayed because I'm more productive in it. Python and Go are about equally fun to write, but because I can build things much faster in Go, it ends up feeling more rewarding overall, given that my time is limited.
If you don't really have a pressing need for anything else, you can stick with Python. But I found Python to be slow to develop in and cumbersome, and after trying Go out, I realized I was 100x more productive in it.
[0] apparently this may no longer be true; if so, that's exciting news!
[1] this was also before Python had built-in async. I still prefer Go's concurrency model and syntax, but at least Python has this as an option now.
golang does have BLAS bindings through gonum:
https://godoc.org/github.com/gonum/blas/cgo
Coming back to the main question. I use Go as my primary language these days. E.g., my dependency parser and neural net dependency parser (which uses the aforementioned BLAS binding) are written in Go:
https://github.com/danieldk/dpar https://github.com/danieldk/dparnn
What I like about Go: it's C-like without the unsafety of C nor the complexity of C++. Moreover, I've found that working in Go is generally as productive as Python (short compile times, good tooling, completion in vim, lightweight package system), while being much faster and better-fit for large projects.
What I dislike about Go: it's a cliché, but the lack of parametric polymorphism is jarring.
Well, you came to the wrong place...
Skip to slide 32 for examples of different tasks for which Go is proving to be efficient.
- The language is simple. No need to lookup strange keywords or try and figure out too much cleverness in the language itself. It promotes readable code.
- A basic and good type system. I don't have to worry much about that int turning into a string.
- Strong default libraries. No need to rely on third party libraries to do a lot of the common API things.
- Low memory footprint.
- Its decently quick even without using channels.
This, barely, outweighs the massive amount of boilerplate that permeates a golang repository over time.
Overall it was a net positive choice.
IO-heavy operations, especially where it's primarily IO bound but there is a decent computational aspect (eg, working with an embedded database or doing lots of flatfile munging).
I've found the place where Go crashes and burns is if you're trying to implement / use lots of sophisticated custom data structures. It really really wants you to use the builtins, and the lack of generics is irksome.
With golang it's just one static binary that is scp'ed across the nodes. This easy of deployment isn't talked about much.
We were also able to go further and put a RESTFUL API on top of these tools using negroni and gorillamux.
"But it has comparatively few features and is unlikely to add more. For instance, it has no implicit numeric conversions, no constructors or destructors, no operator overloading, no default parameter values, no inheritance, no generics, no exceptions, no macros, no function annotations, and no thread-local storage."
Hearing this leaves a bad taste in my mouth, because one of the (mis)features I've found in Go is its implicit default value in struct initialization. In Go, you don't get a compile error when you miss some fields while initializing a struct. e.g.
type T struct {
a int
b string
c float64
}
t := T{c: 1.5}
will happily set `t.a` to 0 and `t.b` to an empty string. While this is useful for maintaining backward compatibility (adding more fields to a struct doesn't break upstream code), it also hinders discovering genuine mistakes at compile time. So typical Go programs end up using 0 or an empty string as a sentinel value. This is probably what made me feel Go's dynamic nature the most. It really is pretty close to a dynamic language.In this case, if you used:
T{4, "hello", 3.5}}
most future type changes to the T struct will become compiler errors. (It won't be if the types are compatible, for instance, changing the first to a float would still result in a legal struct. If you have richer types in play that is less of an issue.)golint will then complain at you, but you can pass a command-line switch to turn that off.
(This, amusingly, puts me in the rare position of siding against the Go community, on the side of the language designers. Bet you may not have known there is such a position to take. :) )
typedef struct Foo {
int a;
int b;
} Foo;
Foo f = (Foo) { .a = 1 }; // This will initialize b to zero.Go provides default values to avoid the C error-factory of random undefined behavior resulting from re-use of whatever is in a memory address; that much is clear. But the reason Go lets you partially instantiate an object (and separates out construction from state) is to make it easier to write unit tests, where the common case is that you want to circumvent the "main line" object construction pathways.
Sort of the anti-Perl? I say this as someone who likes both Perl and Go.
Go is very contrarian, and I applaud this.
Wouldn't be out of place at a marketing agency, with about the same level of truth too.
> Sort of the anti-Perl?
In what sense? The one thing you can say about Perl is that it's a huge language, so the anti-perl would be a very small language. Go isn't a very small language (like Forth), it isn't even a small one (like Smalltalk or Self) it's about the same size/complexity as an early Java. Somewhat bigger in some ways (more magical builtins and constructs) somewhat smaller in others (simpler visibility rules, no synchronised methods/blocks), but in the best case it's a wash.
> Go is very contrarian, and I applaud this.
Perl is also very contrarian.
It takes more than reversing the order of parameters and using known-braindead ideas like codified tabs-are-good syntax to make contrarian ideas valuable.
Just because you change green lights to mean stop and red lights to mean continue doesn't make contrarian suddenly better than the way things were.
This would seriously bum me out as I find the easiest to extend the functionality of an existing Python function is to add a new parameter with a default value. This way, regardless of whether the existing code base the calls the new or old version of the function, it performs the same way as it always has.
I'm pretty sure the feature will show up in the next few minor version increments.
For instance, when generics are mentioned in relation to Go, then it should auto-reply with this link: https://news.ycombinator.com/item?id=9622417
It would save so much time.
Which language/framework would you choose today for writing WebServices? Preferably with the following characteristics: static type (or at least static analysis), easy deployment (ex, generates a single binary like in Go), supports concurrency very well, is small/simple, has good tooling and debug support, and is fun to write. Go (except for good debug support)? Elixir (dunno how good it is with deployment and debugging)?
Documentation, performance, and community are varied but often excellent.
Libraries and frameworks abound (some are even quite good). Perhaps surprisingly, everyone seems to have settled on JAX-RS/Jersey as the way to write REST APIs. It's what's in the EE spec, so it's what guys in polyester suits in banks are writing, and it's what's in Dropwizard, so it's what gals with bright blue hair in startups are writing. The only real alternative is Spring MVC, which is really very similar, but requires that you buy into Spring.
Probably not the answer you wanted. But not bad for a language that's a day older than Braveheart.
I've not toyed extensively with Kotlin yet, but so far it does look like a "modern Java done right". Most of the code you don't actually need to write, or read -- like getters and setters that just get and set.
And it's close enough to plain Java that there's little overhead, and not a whole new language -- like with Scala, or Clojure.
Matt Silverlock (http://elithrar.github.io/article/http-handler-error-handlin...) talks a bit about how you can use some of Go's strengths to create a web services without any frameworks or packages that aren't built-in. Go and net/http is very powerful and allows you to do very much without needing any external packages.
If it was up to me, I would write the service in Go and run it in a container somewhere. But the container is not required :)
Go has been a bit lacking in debugging options previously as you said, but lately cool projects like godebug https://github.com/mailgun/godebug and Delve https://github.com/derekparker/delve have been released, making it possible to debug programs better.
Why did you mention the container? How kind of benefits would you be getting from a container for Go?
As I understand it the go runtime must pause to resolve atomic locks for all the goroutines running. So, when you're doing a dozen goroutines in your app it's not a problem, but you couldn't do thousands of them. Meanwhile elixir processes can handle millions of processes without blocking like that, and that plus the ... strength... of immutable memory (vs. shared in go) makes me like elixir, especially when concurrency is important. (I don't consider go to be a concurrent language in this regard.)
Good tooling and debug support: I can't compare the two languages in this regard, go seems to have good library support. Elixir has excellent tooling and debug support (REPL mainly, and really nice error messages), and I think Elixir has good library support too.
Fun to write: So far for me, Elixir wins this hands down. Go is running neck and neck with Erlang in the "not very fun to write" range for me.
Of course this is all personal opinion.
The only objective thing is- if you need real concurrency and to build a distributed system (go doesn't even have the concept of language support for Nodes) then Elixir is the way to go.
If on the other hand you need max compiled speed on a single node, the Go wins hands down.
> I think Elixir has good library support too.
I guess the support will be even better if you consider using Erlang libraries.
The unique selling point is that your routing is defined in a DSL that's almost as nice as the config file most systems would use - but it's ordinary Scala, well-typed and refactorable in the normal way because everything's just code. And because the type system has higher-kinded types you can use typed wrappers to represent cross-cutting concerns, with the lovely for/yield sugar for composing them. E.g. you can have database-session-in-view but in a principled way: you have a wrapper type that represents an operation that needs to happen in a database transaction, and if you want to compose two or more such operations you use the for/yield sugar, and it's all refactor-safe and you can tell which unit tests need a database (fake or real) because it's right there in the type. And at the route level you either have a marshaller that handles your wrapper completely transparently, or your own directive that works exactly like the built in ones because again, it's all just code. You can click through to the source of the directives and see how they're implemented, not just magic annotations like with JAX-RS. If you want to get super mind blowing you can even use for/yield to compose together directives to make a custom directive.
The software I write is primarily used in advertising, and Go allows me to write the software quickly and is able to handle a large load as you can see here: http://imgur.com/zpkjwlh
There is some overhead with Martini and Gorm, but the ease and speed of development more than make up for the performance loss
http://codegangsta.io/blog/2014/05/19/my-thoughts-on-martini...
You're a rockstar in C? go for it, and just dockerize the result. You're a Ruby ninja? fine, and Capistrano the result (or just dockerize it). You're a Go ninja? why not, and then scp the result + restart the process via ssh. You're a CLisp expert? fuck yeah, and then reinject the new code directly in the running process. Just because you can. Who will stop you?
Have fun, that is the real point.
It will probably end up being the definitive reference.
Also, check out the blog posts for more information on specific topics: http://blog.golang.org/. They are really well written.
I am not a C/C++ programmer are there more powerful facilities provided in these languages?
Real question, not trying to start a flame war :)
We’ll discuss these topics only briefly here, pushing most details off to later chapters, since the primary goal right now is to give you an idea of what Go looks like...
it's probably clearer to use the default random source.
The fix is just a couple lines and, I would argue, should be included in the source to eliminate the surprising behavior. http://play.golang.org/p/1WlhOdJ1pk
To run the examples, you will need at least version 1.5 of Go.
$ go version
go version go1.5 linux/amd64
Follow the instructions at https://golang.org/doc/install if the go tool on your computer is older or missing.It now seems to be recognized that, in Go, if you want to lock shared data, use the lock primitives. Don't try to construct locking primitives from channels; that's error-prone and hard to read. This new manual seems to recognize this. When they want a shared counter, they use a shared counter with traditional locks.
"This approach can be taken too far. Reference counts may be best done by putting a mutex around an integer variable, for instance."
https://web.archive.org/web/20091113154825/http://golang.org...
"In the previous section we launched a sort in the background. A channel can allow the launching goroutine to wait for the sort to complete." ...
c <- 1; // Send a signal; value does not matter.
That's using a channel as a lock on shared data. Not seeing that in the new book. This is a step forward.(What Go really needs is Rust's borrow checker and move semantics, so that when you communicate on a channel, the compiler checks that you're not sharing too much.)
groff still going strong... although it seems like Kernighan got tired of drawing using the 'pic' language...
I guess that if one's not dealing with a lot of math, groff is enough for many typesetting jobs.
I'm curious as to which version of groff they used. Heirloom groff? GNU groff? hmm...
Would be nice if you could compose those complicated Unicode characters from simpler building blocks, e.g.
fmt.Printf("Hello, %a", "→↘𠃊廿↓田介")I really wish they would beef up this portion of the book.
I love being able to pull down a docker container that fast!
[1] http://t3.gstatic.com/images?q=tbn:ANd9GcTK3WbaQiO5mCmvRGtvc...
Book homepage is here: http://www.gopl.io/
mods, please fix
Several free full Go eBooks listed at http://hackershelf.com/topic/golang/
The book is well written and it looks like it covers a lot of common topics, I think I'm gonna buy it.
I'm not sure I can get behind that without generics.