Go
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Functions and Methods
-
Section 4: Concurrency
-
Section 5: Packages and Tooling
-
Section 6: More Standard Library
-
Section 7: Building Services
-
Section 8: Advanced Go
-
Section 9: Go in the Cloud-Native Ecosystem
-
Section 10: Data Structures and Algorithms in Go
-
Section 11: Testing and Deployment
-
Section 12: Practical Projects
-
Section 13: More Standard Library Practice
-
Section 14: More Practice Projects
-
Section 15: Design Patterns in Go
-
Section 16: Interview Practice
-
Section 17: Package fmt In Depth
-
Section 18: Package strings and strconv
-
Section 19: Package os and io
-
Section 20: Package time
-
Section 21: Package sort and container
-
Section 22: Package encoding
-
Section 23: Package net/http In Depth
-
Section 24: Package context
-
Section 25: Package regexp and bytes
-
Section 26: Package errors In Depth
-
Section 27: Package crypto and hash
-
Section 28: Package flag and log
-
Section 29: Package sync In Depth
-
Section 30: More Practice Exercises
-
Section 31: Go Modules and Workspaces In Depth
-
Section 32: Generics Deep Dive (Go 1.18+)
-
Section 33: Testing Package In Depth
-
Section 34: More Interview and Whiteboard Practice
-
Section 35: Package math and unicode
-
Section 36: Package path and filepath
-
Section 37: Package database/sql
-
Section 38: Package text/template and html/template
-
Section 39: Package archive and compress
-
Section 40: Lower-Level net Package
-
Section 41: Package runtime and reflect
-
Section 42: Package embed and io/fs
-
Section 43: Go Assembly and CGO Basics
-
Section 44: Building CLIs and TUIs
-
Section 45: Go Performance Tuning
-
Section 46: More Real-World Projects
-
Section 47: Go in Production
-
Section 48: Go Design Patterns
-
Section 49: Go Interfaces Deep Dive
-
Section 50: Final Practice and Review
106: Mock Coding Interview Walkthrough in Go
Alright, let's put you in the hot seat. Imagine we're in a technical interview. The interviewer hands you a problem: Group Anagrams. You're given an array of strings, and you need to group the ones that are anagrams of each other into separate lists. If you've got "eat", "tea", and "tan", "ate", "nat", "bat", you should end up with [["eat", "tea", "ate"], ["tan", "nat"], ["bat"]].
I'm going to walk through how I'd actually solve this live, including the mistakes I'd likely make and how I'd pivot. This isn't about the "perfect" solution immediately; it's about the process of arriving there using Go's specific toolset.
The "First Instinct" Approach
My first thought is that if two words are anagrams, they'll be identical if I sort their characters alphabetically. So, the plan is simple: iterate through the strings, sort each one, and use that sorted version as a key in a map. The value will be a slice of all the original strings that match that sorted key.
func groupAnagrams(strs []string) [][]string {
groups := make(map[string][]string)
for _, s := range strs {
// I'll sort the string here...
sortedS := sortString(s)
groups[sortedS] = append(groups[sortedS], s)
}
// Then I just need to flatten the map values into a slice of slices
var result [][]string
for _, group := range groups {
result = append(result, group)
}
return result
}
Now, here is where I actually have to write that sortString helper. In Go, strings are immutable. I can't just call a sort method on a string. I have to convert it to a slice first.
Hitting the Map Key Wall
I might try to be clever here and use a slice of integers (a frequency count of letters) as the map key, since that's often faster than sorting. Let's see what happens if I try that:
func groupAnagrams(strs []string) [][]string {
groups := make(map[[]int][]string) // Wait...
// ... logic here
}
If I try to run this, the compiler will scream at me: invalid map key type []int. Right. I forgot for a second that in Go, slices are not "comparable." You can't use them as map keys because the language doesn't have a built-in way to determine if two slices are equal without iterating through them. This is a classic Go gotcha. If I want a frequency array as a key, I'd have to convert that array into a string or use a fixed-size array (like [26]int), because arrays are comparable.
Turning Sorted Slices into Keys
Let's stick to the sorting approach for a moment because it's more intuitive during an interview. To make sortString work, I have to convert the string to a []rune (to handle potential Unicode, though for basic anagrams []byte is faster), sort that slice, and then cast it back to a string so it can actually be a map key.
import (
"sort"
)
func sortString(s string) string {
r := []rune(s)
sort.Slice(r, func(i, j int) bool {
return r[i] < r[j]
})
return string(r)
}
Now the logic holds up. I'm taking the input, transforming it into a "canonical form" (the sorted string), and using that as the bucket ID in my map. It's clean, it's readable, and it leverages Go's map and slice dynamics effectively.
Polishing for Performance
If the interviewer asks, "Can we do better than O(N * K log K)?" (where N is the number of strings and K is the max length), I'd point back to that frequency array idea. Since we're usually dealing with lowercase English letters, a [26]int array is a perfect key.
Unlike a slice, a fixed-size array is a value type in Go. This means map[[26]int][]string is perfectly legal. I don't have to sort anything; I just count the letters.
func groupAnagrams(strs []string) [][]string {
groups := make(map[[26]int][]string)
for _, s := range strs {
var count [26]int
for _, char := range s {
count[char-'a']++
}
groups[count] = append(groups[count], s)
}
result := make([][]string, 0, len(groups))
for _, group := range groups {
result = append(result, group)
}
return result
}
I love this version more. It's O(N * K). By swapping a slice for a fixed-size array, I bypassed the "comparable" limitation of Go maps and improved the time complexity. That's the kind of pivot that makes an interviewer realize you actually know the language internals, not just the syntax.
📋 Practical Task
Implement a "Unique Word Grouping" Tool
Build a function that takes a slice of phrases and groups them based on the set of unique words they contain, regardless of the order of the words or how many times a word is repeated. For example, "the cat and the dog" and "dog and cat the" should be grouped together because they both contain the unique set {the, cat, and, dog}.
Requirements:
- Create a function
groupPhrases(phrases []string) [][]string. - You must handle the "key" problem: since you can't use a slice or map as a map key, find a way to represent the unique sorted words of a phrase as a comparable Go type.
- Ignore case sensitivity (e.g., "The" and "the" are the same word).
- Ensure your final result is a slice of slices.
There are no comments for now.