Skip to content
tezvyn:

Top 30 Easy Go & Rust Concepts Quiz for Beginners

30 easy multiple-choice Go & Rust concept questions, the vocabulary and first principles, the parts you need before anything else makes sense. They come from 30 bites in the Go & Rust library, the gentlest slice of the 144 Go & Rust concept questions in the library. Answer them here or read straight down. Every question carries the correct option, why it is correct, and a link to the bite it came from.

Go web services, Rust backends, systems programming

30 questions. Pick an answer, or open “Show the answer” to read it.

Answers are graded in your browser. Nothing is saved, and no XP or streak is earned here. The app keeps score.

  1. Question 1 of 30

    What is the fundamental principle guiding Go's design?

    Show the answer

    Answer: d · Optimizing for practical engineering challenges in large systems.

    Go was created to solve practical problems like slow builds and complexity in massive codebases, prioritizing engineering concerns such as maintainability and team productivity. It explicitly avoids being a research language or focusing on novel paradigms.

    Read the full bite: Go's Design Philosophy: Engineering Over Novelty

  2. Question 2 of 30

    What is a key advantage of Rust's philosophy of bundling its official documentation with the language installation?

    Show the answer

    Answer: c · It guarantees developers have immediate, offline access to comprehensive learning materials.

    The card states that bundling the documentation ensures every user has immediate, offline access to a high-quality learning resource. Option D is incorrect because documentation adds to the download size, it doesn't reduce it.

    Read the full bite: Rust's Philosophy: Documentation and Community First

  3. Question 3 of 30

    A Go server spawns a goroutine per incoming request, and one handler blocks forever reading from a channel that nothing will ever write to. What happens to that goroutine?

    Show the answer

    Answer: b · It stays alive indefinitely, quietly consuming its stack memory, because Go never force-cancels a blocked goroutine on its own

    Go has no automatic timeout or forced cancellation for a blocked goroutine, so it simply stays parked, leaking its stack, until the process exits or something explicitly unblocks it. The runtime does not kill it after a timeout, a single blocked goroutine does not crash the whole program since Go only reports a deadlock when every goroutine is blocked at once, and the garbage collector does not collect a goroutine that could still be unblocked.

    Read the full bite: Goroutines

  4. Question 4 of 30

    How does a concrete type in Go become an implementer of an interface?

    Show the answer

    Answer: b · By defining all the methods specified in the interface's method set.

    A type satisfies an interface implicitly by implementing its methods, without an 'implements' keyword. Option B accurately describes this structural typing, where a type automatically satisfies an interface if it provides all the required methods. Option C is incorrect because Go does not use an explicit 'implements' keyword.

    Read the full bite: Go Interfaces: Describe Behavior, Not Data

  5. Question 5 of 30

    Regarding variable mutability, what is the fundamental difference between Rust and Go?

    Show the answer

    Answer: d · Rust variables are immutable by default and need an explicit keyword for mutability, whereas Go variables are mutable by default.

    The card explicitly states that Rust variables are immutable by default and require the 'mut' keyword to become mutable, while Go variables are mutable by default. Option A incorrectly swaps the default behaviors of the two languages.

    Read the full bite: Go vs. Rust: Variable Mutability by Default

  6. Question 6 of 30

    Given two slices, s1 and s2, where s2 is created by slicing s1, what happens if you modify an element in s2?

    Show the answer

    Answer: d · The modification will also be visible in s1, because both slices reference the same underlying array.

    Slices are descriptors that point to a segment of an underlying array. When s2 is created by slicing s1, both slices typically point to the same underlying array. Therefore, modifying an element through s2 will also reflect the change when accessing the same element through s1. The most tempting distractor (C) is incorrect because slices do not copy their data when created from another slice; they share the underlying storage.

    Read the full bite: Go Slices: A Window into an Array

  7. Question 7 of 30

    What is the immediate consequence of attempting to assign a value to a Go map that has been declared but not initialized?

    Show the answer

    Answer: c · The program will encounter a runtime panic.

    The card explicitly states that 'Writing to a nil map causes a runtime panic.' A declared-only map is nil, meaning it points to no underlying hash table structure. While some errors are caught at compile time, this specific issue is a runtime problem because the type system allows the declaration, but the operation itself is invalid without an initialized structure.

    Read the full bite: Go Maps: Your Built-in Hash Table

  8. Question 8 of 30

    What happens when a Rust Vec<T> is full and a new item is pushed into it?

    Show the answer

    Answer: a · It allocates a larger memory block, copies all existing items, then adds the new item.

    When a Vec<T> is full, it reallocates by finding a new, larger contiguous memory block, copying all existing elements to it, and then adding the new element. This ensures the vector remains growable. Option D is incorrect because Vec<T> is designed to grow automatically, not to error out when capacity is reached.

    Read the full bite: Rust Vectors: Your Go-To Growable List

  9. Question 9 of 30

    Which action is most likely to lead to incorrect behavior or data loss when using a Rust HashMap?

    Show the answer

    Answer: b · Modifying a key's internal state in a way that changes its hash value after it has been inserted.

    Modifying a key's hash-relevant properties after insertion violates the HashMap's core invariants, leading to undefined behavior like panics or incorrect lookups. While using non-cryptographically secure keys can lead to performance degradation under attack (HashDoS), it doesn't inherently cause the map's internal logic to break or data to be lost in the same way as modifying an inserted key.

    Read the full bite: Rust HashMap: Fast, Secure Key-Value Storage

  10. Question 10 of 30

    To create reusable functionality that can be easily shared across different Rust projects, where should the core logic primarily reside?

    Show the answer

    Answer: a · Inside a library crate, typically rooted at src/lib.rs.

    The card explicitly states, "When you want to create shared, reusable functionality for other projects, you build a library crate." Option C is incorrect because `main.rs` is for the executable's entry point, not for shared logic, which the card advises against.

    Read the full bite: Rust Crates: Your Unit of Compilation

  11. Question 11 of 30

    To make a struct defined within a submodule vegetables (located at src/garden/vegetables.rs) accessible from the crate root (src/main.rs), which visibility declaration is absolutely necessary?

    Show the answer

    Answer: d · The vegetables module, the garden module, and the struct must all be explicitly marked pub.

    The card states that 'Every pub keyword here is essential; without them, the modules and the struct would be private and inaccessible from main.rs.' This means all modules and the item itself in the path must be public. The 'use' keyword only creates a shortcut to an item's path; it does not grant public visibility.

    Read the full bite: Rust Modules: Your Code's File System

  12. Question 12 of 30

    What is the primary mechanism Go uses to identify a program as an executable rather than a reusable library?

    Show the answer

    Answer: a · Declaring `package main` and defining a `func main()` function.

    The card explicitly states that `package main` and its `main()` function serve as the unambiguous signal for the Go compiler to create a runnable executable. Option D is incorrect because `go.mod` manages modules and dependencies, not the program's execution type.

    Read the full bite: Go's Entry Point: The `main` Package and Function

  13. Question 13 of 30

    According to the card, what is the primary factor Go's compiler uses to decide if a local variable should be allocated on the heap?

    Show the answer

    Answer: a · If its address is taken and returned from the function.

    The card states that if a variable "might be referenced after the function returns, it 'escapes' to the heap." Returning its address is a direct way for it to be referenced after the function returns. While dynamic size often leads to heap allocation, the compiler's escape analysis primarily determines allocation based on the variable's lifetime, not solely its size.

    Read the full bite: Stack vs. Heap: Where Go Puts Your Data

  14. Question 14 of 30

    What is the main characteristic distinguishing a Copy type from a non-Copy type during assignment in Rust?

    Show the answer

    Answer: d · A Copy type's assignment duplicates the value bitwise, leaving the original usable.

    For a Copy type, assignment creates an independent bitwise duplicate, allowing the original variable to remain usable. In contrast, a non-Copy type's assignment typically moves the value, invalidating the original variable.

    Read the full bite: Rust's Copy Trait: Implicit Bitwise Duplication

  15. Question 15 of 30

    Which scenario is the most appropriate use case for Go's `error` interface?

    Show the answer

    Answer: d · Providing structured context for an anticipated failure, such as a file not found during an os.Open call.

    The Go `error` interface is designed for expected, handleable failures that provide structured context, as exemplified by a file not found during `os.Open`. The card explicitly states that errors should not be used for unrecoverable, programmer-level mistakes, which are handled by `panic`.

    Read the full bite: Go's `error` Interface: Errors Are Values

  16. Question 16 of 30

    For which scenario is Rust's Option<T> type most appropriately used?

    Show the answer

    Answer: c · When a function's return value might genuinely not exist, requiring the caller to explicitly check for its presence.

    Option<T> is designed for situations where a value might be absent, forcing compile-time handling of that possibility, as described for function returns that can fail. Option D describes the use case for Result<T, E>, which provides specific error details.

    Read the full bite: Rust's Option<T>: Handling Absence Safely

  17. Question 17 of 30

    When is it most appropriate to use Rust's Result enum for error handling?

    Show the answer

    Answer: a · When a function might encounter an expected, recoverable failure.

    The card explicitly states that Result should be used for 'any error that is expected and recoverable,' such as file I/O or network requests. Option D describes when to use panic!, not Result, as panic! is for unrecoverable, catastrophic errors.

    Read the full bite: Handling Errors with Rust's Result Enum

  18. Question 18 of 30

    A Go type defined in one package satisfies an interface declared later in another package, with no edits to the type. How is this possible?

    Show the answer

    Answer: d · Satisfaction is structural: having the required methods is enough, checked at point of use

    Go uses structural typing, so a type satisfies an interface merely by having the matching method set, verified where it is used. There is no implements keyword, registry, or same-package requirement.

    Read the full bite: Implicit Interface Satisfaction in Go

  19. Question 19 of 30

    What happens if a JoinHandle from std::thread::spawn is dropped before calling .join()?

    Show the answer

    Answer: d · The spawned thread continues running, but its completion cannot be awaited.

    Dropping the JoinHandle before calling .join() detaches the thread, allowing it to continue execution independently in the background, but making it impossible to wait for its completion or retrieve its result. The thread is not terminated, nor does the main thread block waiting for it.

    Read the full bite: Rust's std::thread::spawn: Create and Manage OS Threads

  20. Question 20 of 30

    What mechanism signals a Rust channel's Receiver that no more messages are forthcoming, allowing it to shut down gracefully?

    Show the answer

    Answer: a · All Sender instances linked to the channel have been dropped.

    The card states that `recv` returning an `Err` indicates all transmitters have been dropped, which is the standard way to gracefully shut down a receiving loop. Other options describe common patterns in different messaging systems but not Rust's mpsc channels.

    Read the full bite: Rust Channels: Thread-Safe Communication

  21. Question 21 of 30

    For which scenario is go build the most suitable Go command?

    Show the answer

    Answer: b · To create a standalone, distributable executable file for deployment.

    go build is specifically designed to produce a single, statically-linked executable for distribution or deployment, as detailed in the card's "When to use it" section. Options A and C describe the functions of go run and go install, respectively, while option A is not the primary purpose of go build.

    Read the full bite: Go Build: From Source Code to Executable

  22. Question 22 of 30

    What is the primary function of the `cargo build` command when used without additional flags?

    Show the answer

    Answer: c · To compile only the library and binary targets of the current package and its dependencies, without executing them.

    The card explicitly states that `cargo build` by default "only builds the library and binary targets" and "only compiles code; it doesn't run it." Option C accurately describes this core function. Other options describe actions performed by different Cargo commands or with specific flags.

    Read the full bite: cargo build: Compile Your Rust Package and Its Dependencies

  23. Question 23 of 30

    What is the primary role of the `cargo test` command in a Rust project?

    Show the answer

    Answer: c · To automatically discover and run all unit, integration, and documentation tests.

    The card clearly states that `cargo test` is "Rust's built-in test runner, automatically discovering and executing unit, integration, and documentation tests." It explicitly mentions it is "not designed for manual, exploratory testing," making that option incorrect.

    Read the full bite: cargo test: Rust's All-in-One Test Runner

  24. Question 24 of 30

    When is it more appropriate to use `os.Open` to obtain an `os.File` object rather than `os.ReadFile`?

    Show the answer

    Answer: b · When you need fine-grained control over reading specific parts of a very large file.

    The `os.File` object, obtained via `os.Open`, provides fine-grained control like seeking and reading parts of a file, which is essential for large files that cannot fit entirely in memory. `os.ReadFile` is a convenience function for small files, loading their entire content into memory. Option C is incorrect because `os.File` objects require manual closing, typically with `defer file.Close()`.

    Read the full bite: Go's `os` Package: Your File System Toolkit

  25. Question 25 of 30

    Which behavior is characteristic of Go-style command-line flag parsing, distinguishing it from GNU-style?

    Show the answer

    Answer: b · It stops parsing flags as soon as it encounters the first non-flag argument.

    Go-style parsing is stricter about flag placement; it treats any item after the first non-flag argument as a positional argument. In contrast, GNU-style parsing is more flexible, allowing flags to appear anywhere in the command.

    Read the full bite: Go-Style vs. GNU-Style Flag Parsing

  26. Question 26 of 30

    Which scenario most clearly demonstrates the benefit of Go's monotonic clock?

    Show the answer

    Answer: c · Accurately measuring the elapsed time of a function call despite system clock adjustments.

    The monotonic clock's primary purpose is to provide accurate duration measurements that are unaffected by system clock changes, as described in the card. Options A, B, and D relate to wall clock functions or other time package features, not the specific problem the monotonic clock solves.

    Read the full bite: Go's Time: Wall Clocks vs. Monotonic Clocks

  27. Question 27 of 30

    Which statement accurately describes a key difference in how Go and Rust handle string indexing with multi-byte characters?

    Show the answer

    Answer: d · Go's s[i] accesses individual bytes, potentially corrupting multi-byte characters, while Rust's direct s[i] is a compile-time error.

    Go's s[i] provides byte-level access, which can lead to data corruption when dealing with multi-byte characters. In contrast, Rust prevents direct indexing (s[i]) at compile time to enforce character boundary safety, requiring explicit methods like .chars() or careful slicing.

    Read the full bite: Go vs. Rust: Why String Indexing Is Tricky

  28. Question 28 of 30

    When is the Go table-driven test pattern most effectively applied?

    Show the answer

    Answer: d · For functions that have a clear input-output relationship and many distinct edge cases.

    The card states table-driven tests are "especially powerful for functions with clear input-output behavior that need to be checked against many edge cases." Option B describes a scenario where the pattern is explicitly advised against due to complex setup requirements.

    Read the full bite: Go Table-Driven Tests: Test More with Less Code

  29. Question 29 of 30

    What is a key characteristic of Rust's co-located unit tests, placed within a #[cfg(test)] module in the same file as the code?

    Show the answer

    Answer: b · They can directly access and test private functions and internal logic of the module.

    Co-located unit tests are designed to test individual pieces of code in isolation, including private functions, by using 'use super::*' within the test module. They are conditionally compiled with #[cfg(test)] and are excluded from the production binary, making option A incorrect.

    Read the full bite: Rust Unit Tests: Co-locating Tests with Code

  30. Question 30 of 30

    A Rust library's cargo test run fails on a doctest inside a doc comment for a public function, even though every regular unit test in the tests folder passes. What does this tell you?

    Show the answer

    Answer: a · The example code shown in that function's documentation no longer compiles or runs correctly against the current implementation

    Doctests compile and execute the exact code shown in the documentation, so a doctest failure means that specific example is now out of sync with the real API, which is precisely the drift doctests are designed to catch. Option D is wrong because a missing doc comment produces no doctest at all rather than a failing one, and there is nothing flaky about a deterministic compile step.

    Read the full bite: Rust Doctests

Could you explain these out loud?

That is what an interview actually tests. Tezvyn gives you questions like these with what the interviewer is really checking, the answer that lands, and the mistake that ends the conversation, in the four minutes before your next meeting.

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