Skip to content
tezvyn:

Designing a logging abstraction: Go interfaces vs Rust traits

MediumHow cards are made

Summary

ability to design polymorphic abstractions and explain dispatch.

Key points

define a Logger interface/trait with a write method; Go interfaces are always dynamically dispatched; Rust lets you choose static dispatch (impl Trait/generics) or…

What's really being asked

It checks whether you can model an abstraction over multiple implementations and explain precisely how each language dispatches the call, including the choice Rust gives you.

The full answer

The abstraction is a single-method contract for writing a log line. In Go you declare type Logger interface { Log(msg string) error } and write file, network, and stdout types each with a Log method; the consumer is func Process(l Logger, msg string) error. Conformance is implicit. In Rust you declare trait Logger { fn log(&self, msg: &str) -> std::io::Result<()>; } and impl it explicitly for each type. You then choose the consumer signature: fn process<L: Logger>(l: &L, msg: &str) uses generics and is monomorphized into static, often inlined calls, while fn process(l: &dyn Logger, msg: &str) takes a trait object and dispatches dynamically through a vtable.

Key dispatch difference

Go interface method calls are always dynamic: the interface value carries a type descriptor and pointer, and the call indirects through a method table. Rust defaults to static dispatch via monomorphization when you use generics or impl Trait, paying no runtime indirection; you must explicitly write dyn Trait (typically behind a reference or Box) to get dynamic dispatch. To hold a mixed collection of loggers, Go uses []Logger and Rust uses Vec<Box<dyn Logger>>.

The mistakes people make

Saying Rust traits are always dynamically dispatched. Forgetting that a heterogeneous collection in Rust needs dyn. Claiming Go offers a static-dispatch option for interfaces.

What usually comes next

What is object safety and why can not every trait be a dyn? What is the performance cost of a vtable indirection? When would you prefer Box<dyn Logger> over generics?

A concrete example

Logging to all destinations: in Go, loggers := []Logger{file, net, stdout}; for _, l := range loggers { l.Log(msg) } dispatches each call dynamically. In Rust, let loggers: Vec<Box<dyn Logger>> = vec![Box::new(file), Box::new(net), Box::new(stdout)]; for l in &loggers { l.log(msg)?; } also dynamic, but if you instead wrote a generic function over one concrete logger type, those calls would be statically dispatched and inlinable.

Interview question

When designing a Logger abstraction, how does dispatch differ between Go interfaces and Rust traits?

  • a.Go always uses static dispatch; Rust always uses dynamic dispatch
  • b.Go interface calls are always dynamic; Rust defaults to static dispatch unless you use dyn TraitCorrect
  • c.Neither supports holding a heterogeneous collection of implementations
  • d.Both always use static dispatch resolved at compile time
Why?

Go interface methods always dispatch dynamically through a method table, while Rust monomorphizes generics for static dispatch and requires explicit dyn Trait for dynamic. Both can hold mixed collections (a slice of interfaces, or Vec<Box<dyn Trait>>).

Just read this? Test yourself on what you have been reading.

Put your scrolling time to good use

Learn one idea, try a quiz and save useful cards for revision. Tezvyn makes it easy to learn and stay current in your tech field, a few minutes at a time.

The iPhone app is on the way

We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.

Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.

Get it on Google PlayiPhone app coming soon

We are hiring for this. Open roles that interview on go — each one lists the topics its interview covers.

See open roles