Multimedia particles in the style of a tweet, also serving as a changelog to consolidate changes elsewhere in the site. Cross-posted to an atom feed. Frequently off topic.

Golangci-lint 1.55 bundles in testifylint, which must be the best new linter in years, aiming to make calls to the testify package more consistent.

Its best aspect is being able to detect reversed parameters. i.e. require.Equal(t, actual, expected) when it should be require.Equal(t, expected, actual). An example fix from River:

- require.Equal(t, cleaner.Config.RescueAfter, RescueAfterDefault)
+ require.Equal(t, RescueAfterDefault, cleaner.Config.RescueAfter)

But there’s many other good ones. Requiring Len instead of using an equality assertion:

- require.Len(t, job.Errors, 0)
+ require.Empty(t, job.Errors)

Or use of ErrorAs:

err1 := &UnknownJobKindError{Kind: "MyJobArgs"}
var err2 *UnknownJobKindError

- require.True(t, errors.As(err1, &err2))
+ require.ErrorAs(t, err1, &err2)

Published sequence 069, limited visibility.

Never offer a newsletter sign up without linking to at least one existing issue of said newsletter.

Sam Altman ousted from OpenAI and Brockman demoted.

I have nothing intelligent to say about the situation, so I’ll leave it at this: isn’t this just about the most astonishing thing that could have possibly have happened in tech right now?

The highest profile person at the most important company in the most important new technology space, a man presumed king, is fired.

Nanoglyph 041 is published, on Postgres 16, iPhone 15, charging batteries to 80%, and APEC.

Published sequence 065, protesting the CCP, taken during APEC (Asia-Pacific Economic Cooperation) in San Francisco. Xi is staying in the presidential suite about a block away.

Published sequence 064, Paris cool, at Le Grand Bassin Rond.

WeWork filed for bankruptcy last week. With its stock price down 99.5% since peak and whispers rampant, it’d been expected for a while.

I was wondering if it’d change anything operationally. I went in the next day and was seated close enough to the space’s office managers to overhear most conversations as people made their way in throughout the day. There might’ve been one person who brought up the bankruptcy filing. Entirely business as usual.

Despite the bad news, every writeup on the subject has had an amazingly optimistic outlook for the company. This excerpt from The Industry is representative:

First of all, this is America, which means the rich go out different (a good thing btw, but we’ll save it for another day). “Bankrupt” doesn’t mean “gone,” exactly, but there is a hierarchy in terms of who gets screwed the most. The likeliest case is equity shareholders and stockholders get nothing, and debt holders get whatever is left. Someone could buy the company, shed the worst leases, renegiotiate the rest, and operate a leaner WeWork that benefits from stunning spaces built out using ZIRP-era VC dollars. So your nearest WeWork may shut down, but a lot of them, in some form or another, will likely stick around.

Assuming they can get that debt off the balance sheet and their most egregious leases from peak CRE renegotiated, I’d be amazed if WeWork couldn’t recover. It’s a great product with good revenue, and aside from those leases (which would be priced much lower in 2023), it really shouldn’t cost that much to run.

The Ruby on Rails documentary has been published. I watched it this morning. It’s just about the right length (45 minutes), and centers around interviews with DHH, Jason Fried, and Tobias Lütke.

Today, after years of VSCode, I finally found the options to disable its default behavior of automatically adding closing brackets and quotes (i.e. if you type {, it’ll add }, or " to get a second ").

They’re in Preferences (⌘,) under Auto Closing Brackets and Auto Closing Quotes.

I used the default for a long time because I figured that I must be missing something – most of VSCode’s defaults are pretty good, so somebody must find this behavior useful. If I give it a chance, that usefulness will eventually pop out at me.

But after a long trial period, I’m killing it with prejudice. For the life of me I can’t remember one situation ever where an automatic bracket/quote saved me anything beyond the most infinitesimal amount of time, but on the other hand, especially when refactoring, they waste time by doing the wrong thing in 90%+ of cases. I’ll be changing things around within an already existing line, and as I’m adding a bracket/quote, VSCode puts in a closing version even though one already exists. I actually developed muscle memory to tab right and delete the new character.

A similar story for automatically added tags in HTML templates. When writing brand new templates it’s pretty handy to have the closing tags inserted for you, but I find that I’m editing existing templates the majority of the time, and once again, VSCode is constantly inserting closing tags where one already exists.

A rare miss for VSCode. Maybe I just don’t get it.

An unfortunate discovery in Go today: when using go test and running a testable example, the -count flag is silently ignored – a confusing, underdocumented sharp edge for users. That is unless you specified the magic number -count=1, in which case you get the normal test cache busting behavior.

You can find a caveat in help once you suspect the existence of this problem, but the only way to notice it’s happening is that your tests are running suspiciously fast at high -count iterations. No error or warning is produced.

$ go help testflag

        -count n
            Run each test, benchmark, and fuzz seed n times (default 1).
            If -cpu is set, run n times for each GOMAXPROCS value.
            Examples are always run once. -count does not apply to
            fuzz tests matched by -fuzz.

This makes it hard to reproduce intermittent problems in an example test. As a workaround, I’m using a shell loop that runs the test until it returns a non-zero exit code:

while go test . -run Example_customInsertOpts -test.v -count=1; do :; done

I was spelunking some Go internal code today, and came across the definition of testing.TB. See private() at the end:

// TB is the interface common to T, B, and F.
type TB interface {
	Error(args ...any)
	Errorf(format string, args ...any)
	Failed() bool
	Fatal(args ...any)
	Fatalf(format string, args ...any)
	Log(args ...any)
	Logf(format string, args ...any)
	Name() string
	Setenv(key, value string)
	Skip(args ...any)
	Skipf(format string, args ...any)
	Skipped() bool
	TempDir() string

	// A private method to prevent users implementing the
	// interface and so future additions to it will not
	// violate Go 1 compatibility.

The interfaces mixes in a private function to make it impossible for external packages to implement it. This leaves the authors free to add new functions to the interface without worrying about breaking existing user code.

Personally, I hadn’t seen this technique in action before. It’s probably something that most Go APIs could take advantage of.

A new version of goleak (1.3.0) includes IgnoreAnyFunction function which allows a specific function to be ignored at any level of a goroutine’s stack. Previously, only a function at the top layer could be ignored, which forced us to ignore extremely generic functions like time.Sleep.

For example, this ignore, which was ignoring an internal function deep in the standard library (internal/poll.runtime_pollWait):


Becomes this, which property ignores the specific offending goroutine in Pgx:


Archive ⭢