Golang Regexp.FindAllIndex
last modified April 20, 2025
This tutorial explains how to use the Regexp.FindAllIndex
method
in Go. We'll cover its functionality with practical examples.
A regular expression is a sequence of characters that defines a search pattern. It's used for pattern matching within strings.
The Regexp.FindAllIndex method returns a slice of all successive matches of the pattern in the input byte slice. Each match is represented as a two-element integer slice.
Basic FindAllIndex Example
The simplest use of FindAllIndex
finds all occurrences of a word.
Here we locate all "go" instances in text.
package main import ( "fmt" "regexp" ) func main() { text := []byte("go is good, go is great, go is awesome") re := regexp.MustCompile(`go`) matches := re.FindAllIndex(text, -1) for _, match := range matches { fmt.Printf("Found 'go' at %d-%d\n", match[0], match[1]) } }
The method returns slice of [start, end] index pairs. Each pair represents one match location in the input text.
Finding Multiple Patterns
FindAllIndex
can find multiple different patterns. This example
locates both "cat" and "dog" in text.
package main import ( "fmt" "regexp" ) func main() { text := []byte("cat dog bird cat dog") re := regexp.MustCompile(`cat|dog`) matches := re.FindAllIndex(text, -1) for i, match := range matches { word := string(text[match[0]:match[1]]) fmt.Printf("Match %d: %s at %d-%d\n", i+1, word, match[0], match[1]) } }
The alternation operator | matches either pattern. We extract the matched words using the returned indices.
Limiting Number of Matches
The second parameter controls how many matches to return. Here we limit to first two matches.
package main import ( "fmt" "regexp" ) func main() { text := []byte("one two three four five six") re := regexp.MustCompile(`\w+`) matches := re.FindAllIndex(text, 2) for _, match := range matches { word := string(text[match[0]:match[1]]) fmt.Println(word) } }
Setting n to 2 returns only the first two matches. Use -1 to find all matches.
Finding Overlapping Matches
By default, matches don't overlap. This example shows how to find overlapping matches using lookahead.
package main import ( "fmt" "regexp" ) func main() { text := []byte("ababab") re := regexp.MustCompile(`(?=(aba))`) matches := re.FindAllIndex(text, -1) for _, match := range matches { // Note: match[0] == match[1] for zero-width matches fmt.Printf("Found at %d-%d: %s\n", match[0], match[0]+3, text[match[0]:match[0]+3]) } }
The lookahead assertion (?=...) allows finding overlapping patterns. Each match has equal start and end indices.
Finding All Email Indices
This practical example finds all email addresses in text and their positions.
package main import ( "fmt" "regexp" ) func main() { text := []byte(`Contact us at info@example.com or support@company.com`) re := regexp.MustCompile(`[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}`) matches := re.FindAllIndex(text, -1) for _, match := range matches { email := string(text[match[0]:match[1]]) fmt.Printf("Email %s at %d-%d\n", email, match[0], match[1]) } }
The pattern matches standard email formats. We extract both the emails and their exact positions in the text.
Handling Empty Matches
Empty matches require special handling. This example demonstrates their behavior.
package main import ( "fmt" "regexp" ) func main() { text := []byte("a,,b,c,,") re := regexp.MustCompile(`,`) matches := re.FindAllIndex(text, -1) fmt.Println("All comma positions:") for _, match := range matches { fmt.Printf("%d-%d\n", match[0], match[1]) } // Handling empty fields between commas fields := re.Split(string(text), -1) fmt.Println("\nFields:") for i, field := range fields { fmt.Printf("%d: %q\n", i, field) } }
Empty matches appear as zero-length ranges. They're useful for splitting strings while preserving empty fields.
Performance Considerations
For large texts, consider using FindAllIndex
with byte slices
instead of strings for better performance.
package main import ( "fmt" "regexp" "time" ) func main() { // Generate large text var text []byte for i := 0; i < 10000; i++ { text = append(text, "abc123 "...) } re := regexp.MustCompile(`\d+`) start := time.Now() matches := re.FindAllIndex(text, -1) elapsed := time.Since(start) fmt.Printf("Found %d matches in %s\n", len(matches), elapsed) fmt.Printf("First match at %d-%d\n", matches[0][0], matches[0][1]) }
Working with byte slices avoids string conversions. This can significantly improve performance for large inputs.
Source
Go regexp package documentation
This tutorial covered the Regexp.FindAllIndex
method in Go with
practical examples of pattern matching and index retrieval.
Author
List all Go tutorials.