Q&A
What is the Count function in Golang?
Overview
strings.Count is the standard way to count how many times one string appears inside another in Go. It counts non-overlapping matches, scanning left to right. Understanding its signature, the empty-string edge case, and its siblings (bytes.Count, strings.Index) is what this question targets.
graph LR
A["strings.Count(s, substr)"] --> B{substr empty?}
B -->|no| C[Count non-overlapping matches]
B -->|yes| D["Return len(runes) + 1"]
style C fill:#1e1b4b,color:#fff
Signature
func strings.Count(s, substr string) int
Returns the count of non-overlapping instances of substr in s.
Basic Examples
package main
import (
"fmt"
"strings"
)
func main() {
fmt.Println(strings.Count("cheese", "e")) // 3
fmt.Println(strings.Count("banana", "an")) // 2
fmt.Println(strings.Count("hello", "z")) // 0
fmt.Println(strings.Count("aaaa", "aa")) // 2 (non-overlapping!)
}
Note "aaaa" with "aa" gives 2, not 3 - matches don't overlap. After matching the first "aa", counting resumes after it.
The Empty-String Edge Case
Counting the empty string returns the number of Unicode code points (runes) plus one:
fmt.Println(strings.Count("hello", "")) // 6 (5 runes + 1)
fmt.Println(strings.Count("", "")) // 1
This reflects the number of "positions between and around" characters. It's a quirky but defined behavior worth knowing.
Counting Characters / Runes
To count total characters (runes, handling multi-byte Unicode correctly), use utf8.RuneCountInString, not len (which counts bytes):
import "unicode/utf8"
s := "héllo"
fmt.Println(len(s)) // 6 (bytes - é is 2 bytes)
fmt.Println(utf8.RuneCountInString(s)) // 5 (actual characters)
Related Counting / Searching Functions
| Function | Purpose |
|---|---|
strings.Count(s, substr) |
Count non-overlapping occurrences |
strings.Index(s, substr) |
Index of first occurrence (-1 if absent) |
strings.LastIndex(s, substr) |
Index of last occurrence |
strings.Contains(s, substr) |
Boolean: does it occur? |
bytes.Count(b, subslice) |
Same as Count, for []byte |
strings.Fields(s) |
Split on whitespace (count words via len(...)) |
words := len(strings.Fields("the quick brown fox")) // 4 words
Practical Patterns
// frequency of each rune
freq := map[rune]int{}
for _, r := range "mississippi" {
freq[r]++
}
// freq: m:1 i:4 s:4 p:2
// count lines in text
lineCount := strings.Count(text, "\n") + 1
Why This Matters in Interviews
Go interviews use strings.Count to test standard-library familiarity and Unicode awareness. Know the signature, that matches are non-overlapping ("aaaa"/"aa" → 2), and the empty-string special case (len(runes)+1). The deeper signal is the bytes-vs-runes distinction: len(s) counts bytes, while utf8.RuneCountInString counts characters - important for multi-byte UTF-8. Knowing the related Index/Contains/Fields helpers rounds it out.
Common Pitfalls
- Expecting overlapping matches to be counted (they aren't).
- Surprised by
Count(s, "")returninglen(runes)+1. - Using
len(s)to count characters when the string has multi-byte runes (it counts bytes). - Forgetting
strings.Countis for substrings; for word counts usestrings.Fields.
References
- Go
stringspackage: https://pkg.go.dev/strings#Count - Go
unicode/utf8: https://pkg.go.dev/unicode/utf8#RuneCountInString