Golang Regexp.FindIndex
last modified April 20, 2025
This tutorial explains how to use the Regexp.FindIndex
method in Go.
We'll cover basic usage and provide practical examples of finding match locations.
A regular expression is a sequence of characters that defines a search pattern. It's used for pattern matching within strings.
The Regexp.FindIndex method locates the leftmost match in a byte slice. It returns a two-element slice of integers defining the match location.
Basic FindIndex Example
The simplest use of FindIndex
finds the first match in a string.
Here we locate the position of a simple word.
package main import ( "fmt" "regexp" ) func main() { re := regexp.MustCompile(`hello`) text := []byte("say hello to my little friend") index := re.FindIndex(text) fmt.Println(index) // [4 9] }
The output shows the start and end positions of "hello" in the byte slice. Positions are zero-based and the end index is exclusive.
Finding Multiple Matches
To find all matches in a string, we use FindAllIndex
. This example
shows how to locate all numbers in text.
package main import ( "fmt" "regexp" ) func main() { re := regexp.MustCompile(`\d+`) text := []byte("2025 is coming after 2024") indexes := re.FindAllIndex(text, -1) for _, idx := range indexes { fmt.Printf("Found at %v: %s\n", idx, text[idx[0]:idx[1]]) } }
The pattern matches one or more digits. FindAllIndex
returns all
matches with their positions. The -1 means find all matches.
Case Insensitive Matching
We can find matches regardless of case by compiling with regexp.Compile
.
This example shows case-insensitive word matching.
package main import ( "fmt" "regexp" ) func main() { re := regexp.MustCompile(`(?i)hello`) text := []byte("Hello world, HELLO universe") indexes := re.FindAllIndex(text, -1) for _, idx := range indexes { fmt.Printf("Found at %v: %s\n", idx, text[idx[0]:idx[1]]) } }
The (?i)
flag makes the match case-insensitive. Both "Hello" and
"HELLO" are found at their respective positions.
Finding Submatch Indexes
FindSubmatchIndex
locates both the full match and capture groups.
Here we extract date component positions.
package main import ( "fmt" "regexp" ) func main() { re := regexp.MustCompile(`(\d{4})-(\d{2})-(\d{2})`) text := []byte("Date: 2025-04-20") indexes := re.FindSubmatchIndex(text) if indexes != nil { fmt.Println("Full match:", indexes[0:2]) fmt.Println("Year:", indexes[2:4]) fmt.Println("Month:", indexes[4:6]) fmt.Println("Day:", indexes[6:8]) } }
The output shows positions for the full date and each component. Even indexes are starts, odd indexes are ends of matches.
Finding Index in Large Text
For large texts, we can use FindReaderIndex
with an io.Reader
.
This avoids loading the entire text into memory.
package main import ( "bytes" "fmt" "regexp" ) func main() { re := regexp.MustCompile(`important`) largeText := bytes.NewReader([]byte("This is an important notice about something important")) idx := re.FindReaderIndex(largeText) fmt.Println("First match:", idx) }
The method works similarly to FindIndex
but reads from a stream.
It's efficient for processing large files or network streams.
Handling No Matches
When no match is found, FindIndex
returns nil
. This
example demonstrates proper handling of no-match cases.
package main import ( "fmt" "regexp" ) func main() { re := regexp.MustCompile(`missing`) text := []byte("this text doesn't contain the pattern") index := re.FindIndex(text) if index == nil { fmt.Println("Pattern not found") } else { fmt.Println("Found at:", index) } }
Always check for nil
before using the result. This prevents
potential panics when accessing the slice indexes.
Performance Considerations
For repeated searches, compile the regex once and reuse it. This example compares single-use vs reused regex performance.
package main import ( "fmt" "regexp" "time" ) func main() { text := []byte("sample text with pattern to find") start := time.Now() for i := 0; i < 1000; i++ { re := regexp.MustCompile(`pattern`) re.FindIndex(text) } fmt.Println("Recompile each time:", time.Since(start)) start = time.Now() re := regexp.MustCompile(`pattern`) for i := 0; i < 1000; i++ { re.FindIndex(text) } fmt.Println("Reuse compiled regex:", time.Since(start)) }
The benchmark shows significant performance gains from reusing compiled regex objects. Always compile patterns once when possible.
Source
Go regexp package documentation
This tutorial covered the Regexp.FindIndex
method in Go with
practical examples of finding match positions in text.
Author
List all Go tutorials.