Go at Digital Ocean
speakerdeck.com
speakerdeck.com
BTW I'm not sure if this comment is adding to the conversation or if it is too self promotional. If it gets down voted I'll delete it.
Because the slides don’t reflect them very well I thought I chime in. Currently Drone and GoCD both are in the process of decommissioning to fully migrate to Concourse as our single CI/CD platform. Because our current business runs like a clock, you can imagine it’s not a one click process.
Disclosure: I run a company that sells hosted Concourse.
I'm happy that there seems to be some movement. But now we have godep, govendor, glide, dep. and every project uses one or the other. Are they all compatible? Or is it a minefield?
Step 1: Check out code that you want to use. That's actually the only step and you can do it by hand, or with one of a multitude of tools. All the tools differ slightly, and any metadata or manifests or things like that they do aren't compatible, but the code they put in your repository is, enabling anyone to clone a repository, and instantly build the exact version of all your dependencies.
Imports also aren't full git URLs, they can be as a convenience that tells you where to get a package. You can't `go get` a specific tag, but that's fine, because `go get` isn't a package or dependency manager, it's just a convenience to grab code to your system, not to freeze a version as a dependency into your project.
Frankly, the amount of people that put their nose in the air at go is just fine with me, just makes it more of a 'secret productivity tool' I guess.
Edit: not to say it wouldn't have been nice if `dep` had been the one blessed path at version 1. Still, I have extremely little to complain about with the language and tooling since 1.4/1.5.
Once you forked it, you have to change all the imports across the repo, and then it's kinda either very hard to make Pull Requests, or pull the new commits from the original repo.
This is one thing I really dislike about go dependencies.
If you have a solution for this, let me know, I would be very interested to know more about it.
But overall, I love go. I use it all the time anyway.
I threw together an example of doing this with `dep`. I forked Fatih's color package, and am using it as `github.com/fatih/color` no problem: https://github.com/sofuture/colortest (forked dep here: https://github.com/sofuture/color)
It works for you because it's a small project and you are not actually importing other of your own packages inside it.
But if you look at "echo", it import some other "echo" packages inside of it.
Using the original package name: https://github.com/sofuture/colortest/blob/master/main.go#L7
I can refer to my fork: https://github.com/sofuture/colortest/blob/master/Gopkg.toml...
Thank you for the example :)
Edit: I'll fork echo in my example and show you.
Echo is using some imports to their own packages inside the project.
IE: https://github.com/labstack/echo/blob/a098bcd3b0c445dde3d380...
So if I fork "echo", I have to replace the urls in their imports so it imports my fork packages.
Go get does have support for tags, but it was intended for they have code in go get to find tags like go1 and go2 which are as yet unused (I wish they'd used it for dependency version tags like v5.2 etc instead, it may never be used):
https://golang.org/src/cmd/go/internal/get/get.go#L524
Really some simple additions to go get would have gone a long way - recognise semantic version tags like v1.2 on go get and put them in vendor with some command like 'go vendor my/dep -v 1.2'.
Not really sure they need diamond dependencies, updating them automatically up to version x, manifest+lock files and all the other intricacies which in theory a package manager should solve - humans can resolve them as they come up and in real life use they're not a huge deal (as the incredibly simple go get we currently have shows).
> I'm happy that there seems to be some movement. But now we have godep, govendor, glide, dep. and every project uses one or the other. Are they all compatible? Or is it a minefield?
They're not all compatible, but it's not really a problem because (last I checked) the prevailing philosophy was "libraries should not vendor--only binaries" which is to say "libraries shouldn't specify versions for their dependencies; the downstream binary projects should figure out what versions of each library should be used to build the binary". This means dependency tool compatibility isn't a problem because the dependency tooling punts on the dependency-resolution problem altogether, which seems like an even bigger problem.
Remember that this is only painful if you're trying for deterministic builds, and in the absolute worst case, you forego Go's build tooling and use something like Nix. This is absolutely not a reason to change language.
The GOPATH issue will be solved when I can clone a project to anywhere in $HOME and build it without issue.
What's the real difference between `cd ~/dev` and `cd $MYGO` (~/dev/go/src/github.com/myusername)?
Your GOPATH could be set to "~/libs/go:~/code/work for work/contracting/go:~code/personal:~/code/third-party"
which would put any go-get libaries into ~/libs/go and allow using packages from the other folders. Keep in mind that Go will still use these Gopaths like any other Gopath repository; create a src/pkg/bin folder set for use with the compiler
Also people like to keep other artefacts alongside source code like scripts, resources, templates, tools etc and often have an existing elaborate project structure in order to accommodate that. Go forces them to throw that out and use something under gopath. It's annoying and an unnecessary stumbling block for people starting out in Go.
So you just put your code into ~/src/project/a.go and ~/src/project/b.foo (assuming a GOPATH=$HOME).
This is the least of all problems.
export GOPATH="~/go:~/foo"
GOPATH will use ~/go as default for go get and importing and fall back to any further folders specified.It is.
> Is `dep` fixing all that stuff?
Not from what I can tell; it lets you pin to git tags and branches, but the only versioning you'll get beyond that is if the maintainer of your dependency is gracious enough to use tags. It certainly isn't changing the way import paths work. Vendoring is still part of the workflow for projects I've seen using dep. I've heard there's work being done to get rid of the GOPATH nonsense, but from what I can tell people have been saying that for a while, so I'm not optimistic that it'll land any time soon.
'dep' seems great for Noddy projects where all the code you are working on is in a single package, and fails (like most of the vendoring tools) when you need to work on multiple packages. It is has unfortunately been focused on vendoring at the package level rather than at the project level, and has many assumptions buried deeply into the code. The recommendation for larger projects is the 'vg' tool, which wraps 'dep' with some GOPATH tricks to help manage your dependencies at the project level.
I prefer to be conservative about adding dependencies, and to always manually include them into the project.
Maybe you don't know what a conservative attitude about libraries is because you've never seen one.
Your original comment:
> You can be conservative about adding dependencies and still end up with hundreds
No. Just no. If you have hundreds of dependencies, you are by definition not conservative about adding dependencies.
> Database driver
About the only legit thing on the list.
> database utilities
Not needed.
> gRPC framework
Not needed.
> monitoring & metrics
Not needed.
> CLI & configuration tools
NOT NEEDED!
.. etc.
> Drop any item on that list and you are either losing capabilities or have more software to implement yourself
What are you losing by not using grpc? You can do a lot of things by just using the builtin rpc package or the encoding/gob with the http package.
Being conservative about adding dependencies means resisting the urge to add them and figuring out a way to do without them.
Every dependency you add is a potential point of failure and headaches.
Just like every layer of abstraction you create.
The cost for dependencies is huge, so every dependency has to justify itself by giving such a huge benefits that it's worth the cost.
> Cobra
Do you need a special library to handle command line arguments? How complex is your CLI interface? How many commands and sub commands do you have? 10? 20? It's trivial to handle that much manually using the builtin libraries.
> Viper
How hard is it to just read a json file using builtin libraries? How much do you lose by not using "Viper" or whatever?
How many times will you have to read config files? One time when the app launches? Does not justify adding a dependency.
> it is certainly tempting to reimplement things like Cobra, Viper, sqlx, prometheus end point, and everyone knows we should all implement our own crypto
You don't even need to re-implement anything. Just do the simplest thing that works using the standard library.
You know the standard library comes with a crypto package, right?
The mindset you are presenting is the exact opposite of conservative. You are just grabbing every library that you think can save you 20 lines of code.
I will stop instrumenting my projects because its not needed, no matter what operations says about our SLAs, and my gRPC endpoint will stop talking gRPC because its not needed, and it will be more reliable because clients can no longer talk to it by the expected protocol, and I'll ignore the usability requirements of the CLI and configuration management because specification documents and usability requirements be damned, and I'll implement by own helpers for the database code because NIH syndrome is fantastic, and I'm sure my employer will be happy for me to reinvent the wheel. Except I probably won't have an employer any more, because I seem to have stopped delivering the software they tasked me to.
It will be a complete failure when things get so hairy with so many layers and failure points that you can't tell what's going on anymore.
With proper package names via a package manager, usually the name stays the same.
I'll have to disagree there; while having namespaced packages gives some advantages, having a centralized repository gives you things like proper versioning, which is worth all the terrible package names in the world to me.
Also really cool to see all the tooling they've built up -- all of the things mentioned seem really cool, "who's gonna clean up all the stale branches" is definitely a question that gets asked (and answered) at more companies that it probably should.
Rust can be really daunting to look at, and if you compare the rust book to the go language tour, the easiest one to learn is pretty clear -- I get the feeling they won't even regret the choice because the things rust protects you from go sidesteps by giving you slow-but-safe-and-restrictive channels. Go's data race detector also is probably gonna be good-enough for a long time.
However, it's still very much in early days, so there's no particular consensus, other than Tokio being the async I/O component. Much less mature than Go. We'll get there!
I reckon it will end up like the choice between python/js/php/ruby on the backend, where each have their strength and weaknesses, but none are universally better.
If you start from bare micro-framework (set a route, attach a handler), you're eventually going to write some generic function that fetches an entity from a data store. In Go, this becomes a bit of a kludge (interface{} + casting + etc), but in rust it's robustly supported (traits/generic functions).
Of course, if you pick the right library for the database you wouldn't have that issue, but that's just the kind of abstraction/complexity-hiding problem you run into building webapps (from scratch at least) that I think rust is the better tool for. Like I mentoined in another post, basically all the micro-frameworks have the same shape to me at this point: add route(s), add handler function(s), and start the server.
I wouldn't think that web frameworks were the reason -- at this point, almost all the frameworks that aren't django/rails size are the same, set up a route, add a handler, do whatever you need to in the handler, start the server.
python's flask/ruby's sinatra/go's http.server/rust's iron/haskell's servant/clojure's ring are all the same to me at this point, and generally what I'm comfortable starting with (I pick those micro-frameworks over 'batteries-included' django/rails)
That said, Go makes sense for a lot of the things DO does.
I'm partial to GHC's language extension model over a cornucopia of Go pre- and post-processing tools like Java had (e.g. AspectJ and all the tools making use of annotations? or Go processors using comments). It will be easier to improve GHC's GC or complete OCaml's multicore branch than bring Go to the current century of proven programming language features. Go has found a niche as a replacement for C and Python in network programming, which is great. It just doesn't scale as well with project and team size. OCaml's multicore project also introduces algebraic effects (comprehensive alternative to monadic programming) to the mainstream, so I can't wait for OCaml multicore to land in mainline.
For those that rather get everything for free, OpenJDK has initial support of Linux x64, with other platforms being already available on OpenJDK 10 master.
EDIT: typo
EDIT: E.g moving .git/ back and forth or adding extra vetting/linting tools instead of extending `go vet`.
Google's also opensourced Abseil, their C++ standard library (not meant to completely replact STL, to be clear), which contains all kinds of classes which were copied into many existing Google C++ projects in some form or fashion and sometimes incompatibly (e.g. Google's StringPiece found in several projects).
Either way I applaud them for doing a lot to open source projects. It's not something we can take for granted.
I'm a coffee geek, but i'm intrigued at the idea of being a bag geek. How does one geek out over bags? What are the cool things bag geeks know that ordinary people don't?
For instance, I still haven't found the right carry on backpack that's sturdy, doesn't cost $200+, allows me to take clothes for a couple days and a laptop. It's either too big, too expensive, too heavy, too fragile, take your pick. So I can understand how someone can become a bag geek if they have to travel professionally on their own (without assistants who carry your baggage). Bonus points if I can detach a small laptop bag to take with me in order not to leave it at the hotel with the rest of the bag. So far I've always had to carry around the backpack and leave clothes in the hotel room. Pack, arrive, unpack, carry laptop, repack, go home.
I've seen the Go Ruck GR2 and it doesn't fit my requirements.
Having a subdivision of the main compartment bigger than 2 is also important. Laptop, papers, cloth, food maybe.
I'm in Germany and looking for a shop nearby where they have a diverse selection of bags to inspect. I'm kinda tired of ordering bags and having had to send them all back. Amazon is threatening a penalty for returning too often, so there's that :).
First world problems, right?
A bag geek is someone who tries to find the perfect for the current occasion. So if you travel for one week, a bag geek will try to take only one bag. Which material to choose? Are you going to take a laptop with you? Shoulder or backpack? Are you going to bring gifts back to home? Etc... these are all questions that can’t be answered with a single bag. For example checkout Tom Bihn bags and their community of bag geeks (they have a forum).
slide 55 reads: "each string operation takes 21 seconds" (an amount of time which I translate conservatively into tens of billions of operations or gigabytes of in-memory lookups).
How can performance be that bad - I would think it's trivial? Like, I'm not getting what lowercasing can possibly be doing that is so resource intensive. Any ideas?
My approach is to shove everything in $GOPATH/src.
You are right. Programming languages are tools, not ends unto themselves (something you said, not I), and just as I can use tools from Snap-on or tools from Harbor Freight, I'm personally inclined to use tools with superior engineering. Tools that are designed and manufactured to be robust and to last, because they make it so much easier for me to build meaningful things.
I also think it is an unfair comparison to take two of the most awful languages in computer history and use them to make a case for Go's superiority. It is like saying a Fiat 500L is an awesome car because it isn't a Yugo.