I agree, that is one of my most favorite aspects of Go.
go get -u github.com/go/project
If you're writing native Go code, it doesn't matter if there's 0 or 1000+ dependencies, that one command will take care of everything. So there's no need to fear having extra dependencies, and you are welcome to reuse more code.
Go takes the common parts of writing software and abstracts them away. Take any two distinct Go projects, and the only difference will be:
- Import Path
- Actual Code
Everything else works exactly the same no matter what project it is (assuming it follows idiomatic Go package conventions). Docs via godoc.org, standard testing, go vet, http://go-lint.appspot.com/, http://gocover.io/
No need to figure out how to install that particular project/library, how to get docs, how to run tests, etc.
You mean like `bundle install` or `pip install -r requirements.txt` or `npm install package.json`? I mean, it's great that Go has something similar, but it's not like other languages are missing dependency managment...
Mind you that these are compile time dependencies. Go produces static binaries that can run as standalone apps. So only the developer has to install them.
Ruby, nodejs and python have runtime dependencies, thus the user has to install them too (or use the bundled ones if they exist).
Also their package managers have many issues you don't see with go (because go doesn't have a package manager, rather a source code dependency manager).
For example python and ruby have many versions and not everything is available in all versions. What a user will do if he want to run a 2.7 and a 3.x python app?
Sometimes they use the system compiler to produce binaries. I have seen it fail occasionally; for example charlock_holmes on a gentoo hardened system. Npm just floods your filesystem with npm_modules directories. I use a package manager so I won't have to install the same thing multiple times at multiple locations. Also it is very difficult to understand its directory structure. I searched the docs for hours in order to find where it stores the programs I install as a user (its path). Go is difficult to understand too in that aspect but it has all this info in one online document. You read it until you understand it.
Finally there are always the questions; should I use pip or easy_install? What does rvm, what gem and what bundle(r)? Why should users learn them? How may I update my current gems and remove old versions? Where is gruntjs and how do I run it?
Probably many more. If `go get` was good enough as you intended to say why do we have `godep, godeps, gom, gondler, goop, vendorize, party, gpm` and many more? Which one should I pick? It's better do GOPATH="_vendor:$GOPATH" go install or use one of them? Also, should I install go with apt/brew/pac or use gvm?
I like go, I use it for fun and work, but really, is getting annoying seeing all this `gophers` totally out of reality.
There are third party tools for every language.
With go until now I haven't need any of them, so I don't know them. I read go's docs and I do fine with the official tool when I want to compile an app from source.
On the other hand, there isn't a way to not learn about gem, bundle, pip, easy_install, npm when you try to install apps written in their languages. Some times it is easy, as “gem install gollum” and some times it is difficult, as trying to install gitlab.
Haskell I really don't know because any haskell app I ever needed was in my distro's repositories. To be fair most Python packages are too.
The reason that Go can't handle dynamic library dependencies, for the most part, isn't a strength--it's a weakness. I guarantee you that if it could call out to C efficiently, it would. Part of the price it pays for its goroutines is that its relocatable stacks do not play nicely with C calling conventions, meaning it can be extremely expensive to call out to a C routine. For that reason, Go essentially reimplements libc in its own standard library. All the other languages you named don't do that, because they don't have to.
Anyway, Go can't produce dynamically linked libraries yet even for Go applications. It really has no choice but to bundle them into one application.
I agree that this limits Go's use scope. But when you accept that Go is most suited for web apps and some console tools, it is nice and works well for the users and the application packager.
The only package manager (pm) I like, is the pm of the distro I am using. If I am on Fedora, I like yum. When I am on Gentoo I like portage etc.
The problem with most web apps is that they have dependencies that don't exist in your distro's pm. I'll take a static binary over a 3rd party pm any day. Let's not forget that one of the most important reasons for the existence of docker is to not have to set up an app in many different systems.
Go's goroutines as I understand are the same or very similar to Lua's coroutines and WinAPI's Fibers. Right?
For the later two can calling C functions is cheap. I would assume if you run Go with its default one thread option, it's cheap too. (Switching threads or even processes means context switching is what is usually expensive).
No, Go routines are not the same as coroutines in other languages.
In order to provide efficient lightweight threads, Go allocates only a small amount of memory for each stack, growing it as function calls require it by appending another segment in a linked list. This makes thread creation very cheap.
The problem with segmented stacks is that they can cause "stack thrashing." Suppose a goroutine is right at the boundary between two stacks. It calls a function that exhausts the available segment, forcing the allocation of a new segment, which is then added to the linked list. The function runs, and then frees the segment upon return. If this boundary happens to fall within a tight loop, you'll see a severe drop in performance, to the point that it's completely unacceptable.
Recognizing this, Go relatively recently switched away from segmented stacks. It now uses a strategy called relocatable stacks, or contiguous stacks. See https://docs.google.com/document/d/1wAaf1rYoM4S4gtnPh0zOlGzW... for details. Similar concerns prompted Rust to move away from segmented stacks, but as relocatable stacks require a garbage collector that was not a viable way forward for Rust, so it just dropped the idea completely.
The problem with both approaches is that C has no knowledge or support of either segmented or relocatable stacks. This means that calling out to C in Go involves a completely different calling convention that involves switching to a larger stack, running there, and then switching back--which is very expensive, especially compared to languages like Lua where the C FFI is basically free. That's why Go reimplements glibc by performing its own system calls--to avoid the C FFI.
In conclusion, every language feature--no matter how enticing--has a cost.
Unlike Go, many projects (particularly web based) written in these languages have native dependencies (for databases etc.) and it's uncommon for installation to be as simple as you say.
Ruby's Nokogiri for example is very very common and I've never found it simple to install.
Python has psycopg, numpy and a variety of others that are often very complex to install.
Node at least differentiates itself in that most of the database drivers have pure JS fallback implementations, so they'll work without the relevant libraries installed, just not as fast.
I've had issues with installing those libraries involving C-language dependencies that were failing compiling (this was mainly due to the recent Xcode tool update that makes llvm barf sometimes).
It's not going to get simpler than a single executable.
Go takes the common parts of writing software and abstracts them away. Take any two distinct Go projects, and the only difference will be:
- Import Path
- Actual Code
Everything else works exactly the same no matter what project it is (assuming it follows idiomatic Go package conventions). Docs via godoc.org, standard testing, go vet, http://go-lint.appspot.com/, http://gocover.io/
No need to figure out how to install that particular project/library, how to get docs, how to run tests, etc.