Absolutely fantastic domain name!
For anyone who is not quite excited to visit .r* domains directly: https://archive.ph/CAznY
OP here, FWIW I am American, and everything associated with this domain is hosted in America (GCP us-central-1 specifically).
Do the US sanctions against Russia affect your ability to pay for the domain or not really because it all goes through some intermediary like NameCheap or whatever?
I specifically use 101Domain, NameCheap won’t let you buy that TLD. I first registered the domain in 2014, and they very ironically required that I send them a scan of my passport to do so, because .ru domains are so frequently associated with fraud. At some point it may become a problem, but it hasn’t yet.
This is a good practice but it can go too far. If you never actually swap loggers, then it was just wasted effort. It’s best for things where you definitely need to swap, eg to a fake in testing.
I understand this perspective, but the logging thing took me < 10 minutes. I’ve never started to write an implementation just to “have” it.
Modeling dependencies as interfaces delivers a ton of value, even if you don’t swap out concrete implementations in practice.
An interface is effectively a contract, which abstracts, and decouples, the consuming code from its caller. If I use a Logger, I don’t need to care that you’re implementing it with package zap, or whatever. That’s huge. Dependencies are usually an assertion of expected behavior, for which the concrete implementation is incidental – interfaces provide that model.
Whenever I write a bit of code that takes a non-stdlib dependency, I almost always represent it as an interface, defined with the consuming code, and which is implemented by some concrete type owned and provided by the caller.
Same, in the back of my mind I’m still wondering if I might be using a language where one more level of indirection for every call (esp. in tight loops) might have performance implications, but maybe that is just interpreted-language-past-me hollering.
I’ve been bitten by this too many times, and especially by logrus once :P I guess now (as in the last few years) stuff has matured, but (and I guess it shows I haven’t written a lot of Go) but the testing fake story for swapping out loggers didn’t seem great in 2015ish.
I love doing this for side projects and the like, because there you only have to convince yourself. When working with other people, suddenly idiosyncrasies are frowned upon. Shocking, I know.
“Just use the lib’s interface” is a good bikeshed preventer on some of the more tedious stuff on a collaborative project.
This doesn’t just apply to Go, but is a best practice for any languages with a structural type system (as opposed to a nominal type system). I personally follow the same practice in TypeScript.
And it’s a specific incarnation of the adapter and dependency injection patterns if we’re speaking in more general terms.
Thanks for writing about this! As a novice this made the concept of interfaces much clearer. Just to get a better grasp: would you happen to have publicly hosted code that uses this implementation? I would like to see an entire project that takes advantage of this.
Apache Commons rises again …
(For those who remember “clogging” aka Commons Logging.)
I recently added a similar interface to a project because it not only makes it easier to swap out logging backends, but it simplifies test coverage over log events, as it allows one to drop in alternate logger implementations. e.g. a TestLogger  implementation that writes to a chan string, on which test code listens for expected log messages.
I use a subset of slog‘s interface, because before being added to go stdlib, slog had some major interface changes. But, like you said, at some point I think I’m likely to replace that interface with slog.Logger now that it is stable.
Oof, I just realized the comments in that TestLogger are out of date. The shame.