With AI writing a lot more of our code, we need to optimize for the human code reviewer. The key to this is good test coverage and minimizing diffs in changes that humans need to verify. We should strive to separate refactors that don’t change logic from changes that intentionally change logic (bug fixes, feature additions, etc). Separating the two makes it significantly easier to understand…
Someone at work asked the following question: Why write code like this: foo := getFoo() bar, err := getBar() instead of this: var foo Type = getFoo() var err error var bar Type bar, err = getBar(foo) Isn’t the latter more explicit? Isn’t explicit better? It’ll be easier to review because you’ll be able to see all the types. Well, yes and no. For one thing, between the name…
How to “do” enums is a common problem in Go, given that it doesn’t have “real” enums like other languages. There’s basically two common ways to do it, the first is just typed strings: type FlagID string const ( FooBar FlagID = “FooBar” FizzBuzz FlagID = “FizzBuzz” ) func IsEnabled(id FlagID) bool { The problem with this is that string literals (really, string constants) in…
Error wrapping in go 1.13 solved a major problem gophers have struggled with since v1: how to add context to errors without obscuring the original error, so that code above could programmatically inspect the original error. However, this did not – by itself – solve the other common problems with errors: implementation leakage and (more generally) error handling. Fragile Error Handling In 2016,…
Pay remote workers the same as you’d pay local workers. Or vice versa if your local workers are cheap. That’s it. That’s the blog post. It’s 2019, folks. Average home internet speeds are more than enough for video conferencing and every single laptop has a built-in video camera. Conference room video hardware has come way down in price and gone way up in quality. Everyone…
The proposal There’s a new Go proposal in town - try() . The gist is that it adds a builtin function try() that can wrap a function that returns (a, b, c, …, error), and if the error is non-nil, it will return from the enclosing function, and if the error is nil, it’ll return the rest of the return values. This is how it looks in code: func doIt() (string, int, error){ return…
I have been working remotely for about 8 years now. I’ve worked at companies that did it poorly, and companies that did it well. Let me define remote for a minute. I mean fully remote. Like, I can count on one hand the number of times per year I see my coworkers in person and have fingers left over. I was the first remote employee in my division at Mattel, and I helped guide the culture…
I was so happy when I discovered retool . It’s a go tool that builds and caches go binaries into a local directory so that your dev tools stay in sync across your team. It fixes all those problems where slight difference in binary versions produce different output and cause code churn. We use it at Mattel for our projects, because we tend to have a large number of external tools that we use…
func init() in Go is a weird beast. It’s the only function you can have multiples of in the same package (yup, that’s right… give it a try). It gets run when the package is imported . And you should never use it. Why not? Well, there’s a few reasons. The main one is that init is only useful for setting global state. I think it’s pretty well accepted that global state…
I’d like to announce starlight - https://github.com/starlight-go/starlight . Starlight wraps google’s Go implementation of the starlark python dialect (most notably found in the Bazel build tool). Starlight makes it super easy for users to extend your application by writing simple python-like scripts that interact seamlessly with your current Go code… with no boilerplate on your…
A Brief History A question came up at the Framingham Go meetup a while back about why something like Gradle hasn’t taken hold in the Go community. I can’t say that I know for sure what the answer is - I don’t speak for the community - but, I have some guesses. I think part of it is that many projects don’t need a full-fledged build tool - for your typical Go networked…
There’s a new error handling design proposed here . It’s…. not great. Handle is a new keyword that basically defines a translation that can be applied to errors returned from the current function: func printSum(a, b string) error { handle err { return fmt.Errorf('error summing %v and %v: %v', a, b, err ) } x := check strconv.Atoi(a) y := check strconv.Atoi(b)…
So, I don’t really like the contracts defined here . They seem complicated to understand, and duplicate a lot of what interfaces already do, but in a much clunkier fashion. I think we can do 90% of what the design given can do, with 20% of the added complexity. Most of my objection comes from two things: First the syntax, which adds “type parameters” as yet another overloaded…
There’s a disturbing thread that pops up every once in a while where People On The Internet say that comments are bad and the only reason you need them is because you and/or your code aren’t good enough. I’m here to say that’s bullshit. Code Sucks They’re not entirely wrong… your code isn’t good enough. Neither is mine or anyone else’s. Code sucks.…
If you tell the truth, you don’t have to remember anything. —Mark Twain In a code review recently, I asked the author to change some of their asserts to requires. Functions in testify’s assert package allow the test to continue, whereas those in the require package end the test immediately. Thus, you use require to avoid trying to continue running a test when we know it’ll be in a bad…