This is the fourth in my series of best books to learn Go in 2023. Read my conclusion or jump to the others here:
- Go Programming Language for Dummies by Wei-Meng Lee
- Go Programming In Easy Steps by Mike McGrath
- Learning Go by Jon Bodner
- Beginning Go Programming by Rumeel Hussain and Maryam Zulfiqar (this post)
- Learning Go Programming by Shubhangi Agarwal
- Go For Beginners by Edward Thornton
- Learn Go With Pocket-Sized Projects by Aliénor Latour, Pascal Bertrand, and Donia Chaiehloudj
- Go Fundamentals by Mark Bates and Cory LaNou
- The Go Programming Language by Alan Donovan and Brian Kernighan
- Get Programming with Go by Nathan Youngman and Roger Peppé
- For the Love of Go by John Arundel
Beginning Go Programming: Build Reliable and Efficient Applications with Go 1st edition; by Rumeel Hussain and Maryam Zulfiqar, 277 pages. Published November 23, 2022 by Apress.
This book is clearly written with the assumption that the reader has some programming knowledge. Although it’s not especially clear how much. The preface simply says (page xv), “This book is designed to provide knowledge to beginners and help them start developing great Go-based applications.”
The introductory chapter clearly assumes that the reader understands a number of fairly technical terms, such as “pointer arithmetic”, and general programming concepts such as concurrency, object-oriented programming, interfaces, etc.
My first observation about the narration style of this book is that it seems to often assume a lot about the reader’s knowledge. Actually, it’s a worse than that. It’s quite apparent to me that the authors of this book suffer severely from the curse of knowledge. That is, they make the mistake of assuming that you know exactly what they know.
Example: “Go offers much faster compilation times.” Faster than what? The author had something in mind. Proabably whatever other language they knew before Go. Was that Java? C++? I don’t know.
A new topic is often just jumped into, without much explanation or context. For example, this is how buffered I/O is introduced:
Buffered I/O is implemented via the
bufiopackage wraps the
io.Readerobjects and returns a new
Readerobject, which has the necessary interface implemented for utility methods. This wrapping also provides textual I/O assistance and buffering.
While that is (more or less) accurate and correct, this mechanical definition of the
bufio package doesn’t explain what buffered I/O even is, or why one might want it.
It’s also written in a fairly disjointed, pop-corn style. That’s not necissarily bad. It just means each topic gets a short, quick treatment, then the book moves on to the next topic. To illustrate, continuing the buffered I/O section, after the introductory paragraph quoted above, we’re presented with a 13-line code listing, and four sentences of explanation. Then the section ends.
And one last note on thie buffered I/O section.
This section’s code listing is literally the only listing in the entire book that actually includes line numbers. 🤯
Virtually every section contains code listings. And virtually every description explains the code listings by referencing line numbers (e.g. “In Listing 2-7, Line #11…”), but with this single exception, none of the code listings include line numbers! I looked through the entire book to verify this.
Conceptually, the book is broken into two sections. The first section, made of two chapters, covers the introductory material, and the basics of the Go language. This is nearly the first half of the book.
The second half of the book seems to be a somewhat randomly-ordered collection of random Go topics. Some more valuable than others.
The first example in this section demonstrates calculation of the mean of some numbers. From there we move on to maps of strings. Then error handling.
Some topics get covered more than once (such as JSON marshaling and unmarshaling), while others get comically little coverage.
The entire concept of the empty interface, which is quite fundamental to much of the Go language, and is filled with nuance and a big area for confusion for new users, is covered in a single paragraph. No, wait. It’s worse than that. Because that paragraph also covers the use of
iota constant, which has literally nothing to do with interfaces, empty or otherwise. And it’s also a rather confusing topic, that trips up a lot of newbies. Each of these topics really deserves at least a few pages of its own. But we get a single paragraph, barely touching on them together.
Similarly, the only description of generics in the book comes up in a section discussing logging. And the example it provides to illustrate the point doesn’t even use generics.
I had high hopes for this book, as it’s one of the most recently published I could find. I had hoped that would mean it was more up-to-date, and thorough than many of the earlier ones. Boy, was I disappointed.
Let me start with what I liked about the content in this book. Because it’ll be short. So I can get that out of the way quickly.
I like the way the book sets out explaining language basics. First, it describes that Go uses case-sensitive identifiers. It explains that uppercased symbols are exported (or public in C++/C#/Java parlance), and lowercased symbols are unexported (or private).
But it goes downhill from there.
In fact, even that section has a pretty ridiculous technical error. While explaining unexported symbols, it says
a lowercase initial character indicates that the particular method or variable is not exported nor accessible by the rest of the application other than the code block it was declared in.
It may seem like splitting hairs to point out that the correct wording would be “the package it was declared in”, but it’s actually quite a significant difference. And what’s worse, the very next page defines (mostly correctly) what a code block is.
The book either explicitly or implicitly advocates a number of anti-patterns, such as using underscores in variable names.
The book is incredibly inconsistent in formatting and layout. Here are a few examples:
- While describing through built-in data types, a few are mentioned directly by name (i.e.
float64, while others are just described “Boolean” and “Enumeration” (which isn’t even an actual a thing… 🤦))
- Package and function names are inconsistently capitalized. For example, on page 23, we se refferences to the “
IOpackages”, then later “the
fmtpackage”. We also see “Using scanf” in a heading on page 23, and the arguably more correct “Using Scanln” on page 24.
- Throughout the book, exported package functions are referred to as lowercased (which would mean unexported).
This is normally where I’d mention the topics the book does a good job of covering, and those it missed out on. In this case, there’s nothing the book does an adequate job of covering, but there are a few conspicuous things it shamefully misses. There’s no discussion at all of testing in Go, or the
testing package. The two sentences in the book I’ve found about generics contradict each other (one says they don’t exist, the other mentions them, but offers no explanation). Best I can tell, the book makes no mention at all of Go modules, except to claim (erroneously) that Go has no dependency/package management capabilities.
Wow. Where to start.
This book is chock-full of errors.
By page 20 of the book, I had several pages of notes pointing out obvious errors, confusing text, and conflicts. I stopped after that.
I won’t list them all, but here are some of the worst offenses:
Page 19 claims that Go offers an enumeration data type. It doesn’t. Plain and simple.
On Page 15, the book says “In the first line of a Go program, packages are always mentioned.” First off, that’s some very awkward wording. But more important, it’s just blatently false. General package documentation written in godoc must be placed before the package declaration, and build constraints must go before the package declaration, as two counter-examples.
Page 4 inaccurately claims that Go does not support generic programming. Later, though, on page 151, we are told that Go supports generics, but only in a single, cryptic sentence, referencing an example that doesn’t actually use generics.
Page 245 claims that Go does not have its own dependency package management system. This has not been true since Go 1.11, which was released in 2018, 3 years before this book.
On pages 37-38, the authors attempt to demonstrate an “Incorrect Memory Allocation Example”, but they do so with a snippet of code that produces an error completely unrelated to their demonstration. While the screen shot shows the actual error generated by the code, their description completely ingores the actual error it returned.
Here are a few other examples.
- “Interfaces [are] used to specify a set of one or more method signatures.” (p19) — Interfaces can have zero methods, too. This is the empty interface.
- “There are two ways to pass arguments to a function—call by value and call by reference.” (p85) — Go only supports pass-by-value.
The book looks pretty sharp. It has black and white pages, with no illustrations or iconography to be found. That’s great.
The pages are perhaps a bit more narrow than I would prefer, as it seems to lend a “cheapness” feel to it, as each page contains a bit less content than maybe I’d like. And it makes a lot of the code listings feel really crowded. They’d be even more crowded if they had line numbers, as they should!
But to be honest, if the content were at all valuable, I might not have even noticed this.
This is difficult.
I know that multiple people poured months of their lives into creating this book. So I hate to be harsh.
But this book is garbage.
It reads like a high school research paper, written by somebody who googled random features of Go for the first time, without ever having used the language, and wrote up their often-incorrect first impressions into an essay.
If you bought this book, seek a refund if it’s not too late.