Best practices in Go - Time & Space Complexity
When writing Go code, following best practices helps keep programs efficient and easy to understand.
We want to see how these practices affect how fast the program runs as it grows.
Analyze the time complexity of the following Go function that finds the first duplicate in a list.
func firstDuplicate(nums []int) int {
seen := make(map[int]bool)
for _, num := range nums {
if seen[num] {
return num
}
seen[num] = true
}
return -1
}
This code checks each number once and uses a map to track which numbers appeared before.
Look for loops or repeated steps in the code.
- Primary operation: Looping through the list once.
- How many times: Once for each number in the list.
As the list gets longer, the number of steps grows in a simple way.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 checks |
| 100 | About 100 checks |
| 1000 | About 1000 checks |
Pattern observation: The work grows directly with the size of the list.
Time Complexity: O(n)
This means the time to finish grows in a straight line as the input list gets bigger.
[X] Wrong: "Using a map makes the code slower because it adds extra steps inside the loop."
[OK] Correct: The map lets us check for duplicates quickly, so overall the code still only looks at each number once, keeping it fast.
Understanding how best practices affect time complexity shows you can write code that works well as data grows, a skill valued in many coding challenges.
"What if we replaced the map with a nested loop to check duplicates? How would the time complexity change?"
Practice
Solution
Step 1: Understand variable naming importance
Clear and descriptive names help others understand what the variable holds.Step 2: Evaluate each option
Using single letters or special characters makes code confusing. Very long names are hard to read.Final Answer:
Use clear and descriptive names that explain the variable's purpose -> Option AQuick Check:
Clear names improve readability [OK]
- Choosing short, unclear variable names
- Using special characters in names
- Making names unnecessarily long
Solution
Step 1: Identify correct error check syntax
In Go, errors are checked with 'if err != nil' to detect an error.Step 2: Check each option's error handling
result, err := doSomething() if err != nil { fmt.Println("Error occurred") } prints an error message when err is not nil, which is correct. result, err := doSomething() if err == nil { fmt.Println("Error occurred") } checks err == nil incorrectly. result, err := doSomething() if err = nil { fmt.Println("Error occurred") } uses assignment '=' instead of comparison '=='. result, _ := doSomething() fmt.Println(result) ignores the error by using _ and prints the result anyway, which is incorrect.Final Answer:
result, err := doSomething() if err != nil { fmt.Println("Error occurred") } -> Option CQuick Check:
Check error with 'err != nil' [OK]
- Using '=' instead of '==' in conditions
- Checking 'err == nil' to detect errors
- Ignoring errors without handling
package main
import "fmt"
func main() {
nums := []int{1, 2, 3}
sum := 0
for _, n := range nums {
sum += n
}
fmt.Println(sum)
}Solution
Step 1: Understand the loop and sum calculation
The loop goes through each number in nums: 1, 2, 3 and adds them to sum.Step 2: Calculate the sum
sum = 0 + 1 + 2 + 3 = 6Final Answer:
6 -> Option AQuick Check:
Sum of [1,2,3] = 6 [OK]
- Concatenating numbers as strings
- Starting sum from wrong initial value
- Misunderstanding range loop syntax
func divide(a, b int) int {
return a / b
}
func main() {
result := divide(10, 0)
fmt.Println(result)
}Solution
Step 1: Identify the problem with division by zero
Dividing by zero causes a runtime panic in Go, which must be prevented.Step 2: Choose the fix that prevents panic
Adding error handling to check if b is zero before dividing avoids the panic. Changing return type or removing function does not fix the error. Go does not handle division by zero automatically.Final Answer:
Add error handling to check if b is zero before dividing -> Option BQuick Check:
Prevent division by zero [OK]
- Ignoring division by zero errors
- Assuming Go handles zero division safely
- Changing return type without fixing logic
Solution
Step 1: Understand best practices for function design
Functions should be simple, clear, and handle edge cases like empty input without panicking.Step 2: Evaluate each option
Use a simple loop to count words, return the map, and handle empty input gracefully uses a simple loop and handles empty input gracefully, which is best practice. Use nested loops to count words multiple times for accuracy is inefficient with nested loops. Return a pointer to the map and panic if input slice is empty uses panic and pointers unnecessarily. Use global variables to store counts and update them inside the function uses global variables, which reduces clarity and safety.Final Answer:
Use a simple loop to count words, return the map, and handle empty input gracefully -> Option DQuick Check:
Simple, clear, safe function [OK]
- Using complex nested loops unnecessarily
- Panicking instead of returning errors
- Using global variables inside functions
Ready to prove it?
Pass the test and this pattern moves unknown
