Everyone is excited that after a decade or so of devs asking for generics, the Go programming language is getting generic types and functions in Go 1.18 in Q1 2022. Generics are no doubt going to lead to a lot of experiments, some good, some bad, some just weird. Go 1.18 is also poised to lead to an increase in software reliability by including fuzzing as part of the standard testing package. But today, I want to look at some minor changes in Go 1.18 that might otherwise get lost in all the excitement around the marquee features.
Go is a language designed by Google for use in a modern internet environment. It comes with a highly capable standard library and a built-in HTTP client. I’m on the record as being against including a lot of dependencies. So why did I end up writing my own HTTP client helper library for Go?
Suppose that thirty something years ago, you were a middle manager at a large international bureaucracy, and a proposal landed on your desk that began like this:
Multimedia is a way to link and access information of various kinds as a honeycomb of nodes in which the user can flit at will. It provides a single user-interface to large classes of information (reports, notes, data-bases, computer documentation and on-line help). We propose a simple scheme incorporating servers already available.†
Whenever this topic comes up, I’m used to seeing other programmers declare that the solution is simply to make something better. I understand where this thought comes from; when you have a hammer, everything looks like a nail, and it’s comforting to think that your primary skill and passion is exactly what the problem needs. Making better tools doesn’t do anything about the backwards profit motive though, and besides, have you tried using any of the centralized alternatives lately? They’re all terrible. Quality of tools really isn’t what we’re losing on.
No, the solution has to be political. That’s uncomfortable for me, as it probably is for you too. Software I can do, politics though? That’s hard. Something needs to change about these profit motives though. I’m not arrogant enough to declare that I know the one true answer here, I doubt there even is one true answer.
An example I bring up that people sometimes don’t know about is that when Time Warner bought AOL in 2002 one of the conditions from the FCC was that AOL open up its instant messenger platform before going into videoconferencing. The Bush administration ultimately just decided to just ignore the condition. But you can imagine another universe where instead of jumping from AOL to GChat to Slack to Discord every few years, we could just… use an instant message client and expect it work with whatever servers our friends and companies happen to use. We don’t live in that world because there wasn’t the political will to create it.
Update: Want to listen to a podcast about go:embed instead of reading a blog post? Check out Go Time episode 171.
I have previously written about how to use
//go:generate. It exists to “to automate the running of tools to generate source code before compilation.” Now there is a new feature in Go that eliminates many uses of source code generation. In addition to the remarkable new flag.Func feature, Go 1.16 also introduced a new
//go:embed directive that allows you to include the contents of arbitrary files and directories in your Go application. To demonstrate some of the capabilities of
//go:embed, I have made an example repo which I will explain in this post.
The basic idea of embedding is that by adding a special comment to your code, Go will know to include a file or files. The comment should look like
//go:embed FILENAME(S) and be followed by a variable of the type you want to embed:
byte for an individual file or
embed.FS for a group of files. The
go:embed directive understands Go file globs, so patterns like
files/*.html will also work (but not
**/*.html recursive globbing).
You can read the official docs for a complete technical explanation, so here let’s take a look at some examples to see what’s possible.
Go 1.16 is shaping up to be one of the most exciting releases of Go in recent memory. Among its new features is the
//go:embed directive and the reorganization/deprecation of
io/ioutil. It’s not due out until February 2021 (Edit: it came out Feb. 16, 2021), but now I would like to write about a minor change to the standard library flag package that might otherwise be missed in the sea of changes:
I proposed and implemented
flag.Func. I have made minor contributions to the Go project before, but this is the first time I’ve added a whole top level function to the standard library, so I’d like to explain a little about what it does and the process of getting it accepted into the Go standard library.
First, some notes about who this advice is for: I am assuming you’re working for a small team with no Quality Assurance testing department making a content focused site. If you have a large team that actually QA tests IE11, this advice may not apply to your situation. If you’re just doing personal projects for fun, you should have already dropped ES5 years ago. If you’re making more of an app than a content site, you probably should have cut off IE11 years ago, but the calculations are more complex and site specific.
The promise of Web Components was that we’d get this convenience, but for a much wider range of HTML elements, developed much faster, as nobody needs to wait for the full spec + implementation process. We’d just include a script, and boom, we have more elements at our disposal!
Or, that was the idea. Somewhere along the way, the space got flooded by JS frameworks aficionados, who revel in complex APIs, overengineered build processes and dependency graphs that look like the roots of a banyan tree.
I think the issue is deeper than Verou’s complaints, although those are valid. Web Components don’t actually to solve the problem they purport to solve. The pitch is “get semantic elements from across the web!” But those are wrong problems to try to solve.
The other day, I was reading a website about some historical documents, when I saw that it had an error message on top:
Some quick searching online for the error message revealed that it was caused by a mismatch between the site’s versions of PHP and WordPress. Older versions of WordPress had a bug in the
switch statement of a certain localization component, and later versions of PHP dump a warning about this bug out to the end user HTML. When I came back to the site a few days later, it had been fixed.
The ultimate reason for my seeing for the error message as a random reader is that PHP has too many ways to deal with errors:
Builtin PHP functions, and therefore any PHP project, have a whole range of error handling mechanisms — errors, warnings, returning error values, and exceptions. At every point, calling code needs to know which system will be used to handle errors.
PHP often chooses to send warnings like this right out to the end user because it doesn’t trust operators to actually read their Apache logs. Such a practice would be very out of place in the Go programming language.