tezvyn:

Compare Go's error tuples to Rust's Result for I/O

AI-drafted, machine-checkedSource: go.googlesource.comintermediate

Tests trade-offs between Go's explicit error returns and Rust's Result type. Contrast Go's inline err checks with Rust's ? operator, noting verbosity versus compile-time exhaustiveness. Never call Result an exception or claim Go ignores errors.

WHAT THIS TESTS: The interviewer wants to see if you understand the design philosophy and mechanical differences between two explicit error handling models. Go uses multiple return values where the caller must check the error immediately, making every decision visible but creating repetitive boilerplate. Rust encodes success and failure into the type system via Result<T, E>, leveraging the compiler to enforce handling through pattern matching or the try operator. The question specifically probes whether you recognize that Go's model is opt-in discipline while Rust's is compile-time law, and whether you can articulate the ergonomics trade-off between verbosity and guarantee.

A GOOD ANSWER COVERS: First, explain that Go returns (value, error) tuples where ignoring the error is syntactically legal but socially unacceptable; the compiler will not stop you. Second, describe Rust's Result<T, E> as an algebraic data type where unwrapping or propagating with ? is type-checked; ignoring a Result triggers a compiler warning or error unless explicitly discarded. Third, contrast the file not found scenario: in Go you write if err != nil after os.Open, often returning fmt.Errorf wrapped context, while in Rust you use File::open(path)? inside a function returning Result, letting the error bubble with zero boilerplate. Fourth, note that Go's explicitness makes all control flow visible at the cost of noise, whereas Rust's ? operator hides some flow but preserves explicit types. Fifth, mention that Go 2 draft designs acknowledged this exact pain point by proposing lighter syntax because too much checking crowds out handling.

COMMON WRONG ANSWERS: Claiming that Go has no error handling rigor or that Rust's Result is just syntactic sugar for exceptions. Saying that Go's errors are exceptions. Asserting that Rust prevents all runtime failures; it prevents unhandled Results at compile time, but I/O can still fail at runtime. Suggesting that Go's defer and error checks solve the same problem as ?; they do not, because defer is cleanup, not propagation. Ignoring the context wrapping pattern in Go that the canonical reference highlights as critical for operability.

LIKELY FOLLOW-UPS: How would you add context to a Go error without losing the original? When is it appropriate to panic in Rust versus returning Result? How does Rust's ? operator interact with custom error types and the From trait? If you had to interleave cleanup like removing a partial file on copy failure, how does the explicit Go model help or hurt compared to Rust? What is the zero-cost abstraction story for Result?

ONE CONCRETE EXAMPLE: Consider opening a configuration file. In Go: f, err := os.Open("config.json"); if err != nil { return fmt.Errorf("loading config: %w", err) }. The check is manual and the wrapping is manual. In Rust: let f = File::open("config.json")?; the ? expands to an early return of Err if needed, and if the calling function returns a compatible Result, the error converts via From and propagates with one token. If you forget the ? in Rust, you get a Result handle, not a File, and the compiler complains. If you forget the err check in Go, you get a nil file handle and a runtime panic on use.

Read the original → go.googlesource.com

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.