This blog post is inaccurate. The only information an error is required to implement is their string representation. You can add whatever you want on top, there are no further restrictions.
It's true that you can add additional information via structs or even just `fmt.Errorf`, but I disagree that the blog post is inaccurate. Fundamentally Go's error handling is very much string-centered. All the extra encapsulation you add via structs implementing the `error` interface just make things worse, because of the poor design to check those types (`errors.As` is a monstrosity).
I was trying to say that eventually, errors in Go distill to strings. Of course the type which represents errors can be anything, I thought it is obvious and it is also mentioned in the introduction section which you may have skipped.