When I first got into go, a few of the Go Opinions kinda rubbed me the wrong way.
- I have to source GOPATH in my rc files? Annoying.
- File paths are network URI's? Ugly.
- I have to deal with every err != nil? Verbose.
But over time I've grown to love go more than almost any language (python is still bae, especially with type hints, and even then, it's close).
- dependency pathing is a pain in most other languages. Singular source of truth is great (I've had virtualenvs leak and cmake do bizarre things when multiple libs are on the file tree)
- host/paths are file/paths. I love this pattern now. It's just so obvious and natural.
- ok the err != nil still drives me nuts. But it drives me to write things in a way where I don't need to deal with errors as much. Reduces fractal complexity and paths through the code. It also forces "the buck stops here" sort of pattern where you have some atrium which is resiliant and is where most errors bubble up to
> dependency pathing is a pain in most other languages
This has been a solved problem in the Ruby community for nearly a decade thanks to bundler. When I first started writing Ruby it had all the same problems as other languages, there were various attempts to solve it (similar to virtualenvs) but nothing really worked properly. Then bundler came along, and even from early releases it had pretty much figured it out.
The way it works is by having a human generated manifest file with a list of libraries you think you need (Gemfile) and the tool will then fetch those libraries (they can be installed in a vendor directory or globally for the specific Ruby version). You don't need to specify versions or deps (but can if required), as when the tool runs it will generate another manifest file (Gemfile.lock) which lists the versions of all libraries and their dependencies. Both files should be committed, so when you coworker checks out the project they know they have the exact same versions as you. There's another command to list outdated libraries, and to upgrade all or a specific library later.
The tooling checks the versions of libraries on every execution (unlike npm or yarn) and spits out an error if your local versions don't match the manifest. It automatically creates wrappers around binaries so you don't need to prefix commands from other tooling. There's built in support for installation in a deployment environment, so you don't install testing libraries there.
Together with tools like rvm/rbenv, it makes managing multiple Ruby versions and multiple projects, just work.
Python doesn't really. It's quite funny that Python has much better library dependencies available but Ruby has a much better system for managing library dependencies.
cargo and bundler share some core contributors, for example wycatz (Yehuda Katz), who held a talk about the common concepts and differences at the rubyconf portugal: https://www.youtube.com/watch?v=Bwk8mdU6-ZY
I am an average Go programmer, so I may not be deep into Go as you might be. However the mention of GOPATH catches my eye. All my issues with GOPATH went away for me when I started using the Go Modules: https://blog.golang.org/using-go-modules. Also Go's approach to err is one the reasons I started gravitating to Go -- my old Go code is more readable because of the verbose (error as strings in my code) and hence easier to maintain. Go is a surprisingly practical language for distributed, system oriented, undertakings I'd say
I'm not going to lie, I never understood why the gopath was so hard for people until I saw a friend using it.
The go developers where all unix heads, and as unix heads setting a path env variable was so natural it almost doesn't bear mentioning.
A unix dev is going to follow the following flow:
cd into the project i'm working on in the terminal (I use fasd for this)
export my gopath from history (ctrl+r GOPATH=)
launch emacs on the files I need
develop
However, many "younger" devs grewup with IDE's. They interact with a project by launching goland, which means mucking with this stuff isn't first class.
Not that it adds much, just some food for thought on why GOPATH existed and you found it clunky.
>- ok the err != nil still drives me nuts. But it drives me to write things in a way where I don't need to deal with errors as much. Reduces fractal complexity and paths through the code. It also forces "the buck stops here" sort of pattern where you have some atrium which is resiliant and is where most errors bubble up to
This was actually a huge flaw in the design of go. The way forward for this type of thing was sum types but go failed to implement this modern programming concept hence why your stuck with it. See how rust handles errors... that is the proper way.
Nor have I had problems, simply saying it is too much hassle for little gain so I rarely bother, whereas with other languages it is a breeze so I update all the time.
Please document your workflow to update and compare it to other modern langs, it's all relative.
> Note that golang-go installs latest Go as default Go. If you do not want that, install golang-1.13 instead and use the binaries from /usr/lib/go-1.13/bin.
> If that's too new for you, try:
> $ sudo add-apt-repository ppa:gophers/archive
> $ sudo apt-get update
> $ sudo apt-get install golang-1.11-go
Am I being trolled here?
How would you compare this for both memorability and user experience compared to say "rustup update"?
Please take a step back and look at that question without personal bias. Please!
This comparison is entirely unfair, because you're not comparing the same thing. This is what one has to do to install Rust:
# Install rustup
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# It automatically installs the latest version
This is what one has to do to install Go:
# Add the PPA
sudo add-apt-repository ppa:longsleep/golang-backports
# Fetch information from the PPA
sudo apt-get update
# Install Go
sudo apt-get install golang-go
1 command vs 3, but in both cases only one "odd one" you have to remember specifically. More important, however, is the fact that from now on Go will update along with the rest of you system. You upgrade your system like this:
# Upgrade the system
apt-get update && apt-get upgrade
Now I'm not trying to say rustup is necessarily worse than Go, because it does offer advantages, but for the simple use-case of always running stable it adds an extra step rather often, instead of once.
Updating Go: Search a bunch of stuff and then do the stuff some random website tells you.
Entirely stand by my earlier statements. Apparently the thousands of paid computer scientists at google are simply incapable of automating the basic process to update their lang. It's utterly absurd and should be actively mocked by anyone with half a clue. We should mock this stuff, we really should, it's hilariously dumb.
How are all the people getting paid SF wages literally incapable of creating "go update"?
> Updating Go: Search a bunch of stuff and then do the stuff some random website tells you
No, updating Go just happens when you update your system. You don't need a separate command to do it. All of the other stuff you mentioned in your previous post is about downgrading Go.
That is good advice. I really should document it but only use go now and then for various reasons and never seem to enjoy updating, don't really have a horse in this race. It just feels so clunky, which was my original point.
Now you can `rustup install <version>` easily with everything taken care of. Of course, the latest stable release is automatically installed already. And Rust provides automatic install scripts for Windows, Mac, and Linux. Whereas Go is more involved than is expected for any modern language.
You can just download the go tarball and go from there. Technically you don’t need to install Go, you don’t need environmental variables set etc.
But I do get your point. You are absolutely right that go doesn’t hand hold you through that process and thus a thousand different people have a thousand different methods for doing it.
Well, using apt is one of the standard ways of installing/updating software on Linux, so most advanced Linux users should be familiar with that. But I'm sure you can also use a graphical package manager to do the same thing. "Rustup" on the other hand is a customized rust-specific tool, so of course it's easier to use (once Rust is installed)
The idea of everyone repeating themselves over and over again seems to be almost desirable amongst the community. The concept of DRY is essentially dead as far Go is concerned.
Why exactly can the core team not write this tooling? Why should thousands of independent people do it all themselves to varying degrees? It's a laughable situation.
As far as I know, most new features are opt in - I’d be curious what issues you’ve seen? I recall one recent one that bit me in dependencies on private repos is the new mirror/sum where we need to `export GOPRIVATE=github.com/<us>`. In a way I’m thankful it was so simple, but while I figured out what happened I wasn’t very happy.
Go Modules are opt-in if you are trying to submit pr's? Either you use >1.13 or you don't submit the pr.
I hate to be the rust shill but updating it is "rustup update" I dont have look anything up nor put in any effort, why exactly should a common process which will happen millions of times be so hard for Go to replicate? It's absurd and should be called out.
Updating out of the box is a massive pain and I stand by that statement, it's hilarious how people get so defensive of what is absurdly poor UX for a modern language.
Docs for anyone interested. You need to uninstall the previous version before going through this process. Again to reiterate, all it take in rust is "rustup update".
- I have to source GOPATH in my rc files? Annoying.
- File paths are network URI's? Ugly.
- I have to deal with every err != nil? Verbose.
But over time I've grown to love go more than almost any language (python is still bae, especially with type hints, and even then, it's close).
- dependency pathing is a pain in most other languages. Singular source of truth is great (I've had virtualenvs leak and cmake do bizarre things when multiple libs are on the file tree)
- host/paths are file/paths. I love this pattern now. It's just so obvious and natural.
- ok the err != nil still drives me nuts. But it drives me to write things in a way where I don't need to deal with errors as much. Reduces fractal complexity and paths through the code. It also forces "the buck stops here" sort of pattern where you have some atrium which is resiliant and is where most errors bubble up to