Read a file into a byte slice in Go and Rust
This tests standard-library convenience APIs for slurping files. In Go, use os.ReadFile (1.16+) returning ([]byte, error). In Rust, use std::fs::read returning Result<Vec<u8>>. A red flag is opening a file and looping over reads when a one-liner exists.
WHAT THIS TESTS: This question probes whether you know the modern, idiomatic one-liners for reading an entire file into memory in two systems languages, and whether you understand the subtle differences in their type systems and error handling. It separates candidates who have internalized the standard library from those who only know low-level file manipulation. The interviewer cares that you can name the right function, know the exact return types, and understand when to reach for these APIs versus streaming or memory-mapping.
A GOOD ANSWER COVERS: First, state that Go uses os.ReadFile, introduced in Go 1.16 as a replacement for the older ioutil.ReadFile, and that it returns a slice of bytes plus an error in the form ([]byte, error). Second, state that Rust provides std::fs::read, which is documented as a convenience function wrapping File::open and read_to_end, and that it returns Result<Vec<u8>>. Third, note that both APIs automatically handle opening the file, allocating a backing buffer, and reading to completion, including retrying on interrupted system calls in the Rust case. Fourth, briefly mention that these are appropriate for small to medium files where loading the entire contents into RAM is acceptable.
COMMON WRONG ANSWERS: A major red flag is describing a manual five-step process, opening a file, making a buffer, looping with Read or read, and accumulating bytes, when the question explicitly asks for the standard-library convenience function. Another red flag is naming the deprecated ioutil.ReadFile without noting it is obsolete since Go 1.16. Confusing the return types is also damaging, for example saying Go returns a Vec<u8> or that Rust returns a plain byte slice without the Result wrapper. Finally, claiming these functions work on directories or special files, or ignoring that they return errors when the path does not exist, shows shallow understanding.
LIKELY FOLLOW-UPS: The interviewer may ask how these functions behave with very large files, which opens a discussion about memory limits and when to use streaming readers like bufio.Scanner or io.Reader in Go, or BufReader in Rust. They might ask about error handling patterns, such as when to propagate with the question-mark operator in Rust versus explicit if err != nil checks in Go. Another follow-up is comparing these to memory-mapped files or asking about the performance implications of repeated allocations. You might also be asked to write a small wrapper that adds a size limit or converts the bytes to a string.
ONE CONCRETE EXAMPLE: Imagine a configuration loader that needs to read a small JSON file at startup. In Go, you would write data, err := os.ReadFile("config.json") and then check err before unmarshaling. In Rust, you would write let data = std::fs::read("config.json")? and then proceed to parse. Both lines accomplish the same goal, but the Go version uses a multi-value return while the Rust version uses the Result monad, reflecting each language's core error-handling philosophy.
Read the original → doc.rust-lang.org
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.