Golang Regexp.SubexpNames
last modified April 20, 2025
This tutorial explains how to use the Regexp.SubexpNames
method
in Go. We'll cover named capture groups and provide practical examples.
A named capture group is a regular expression feature that allows assigning names to capturing parentheses. This makes patterns more readable.
The Regexp.SubexpNames method returns a slice of names for the named capture groups in the regular expression. The first element is always the empty string for the entire match.
Basic SubexpNames Example
The simplest use of SubexpNames
shows the names of capture groups.
Here we examine a pattern with named groups.
package main import ( "fmt" "regexp" ) func main() { re := regexp.MustCompile(`(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})`) names := re.SubexpNames() for i, name := range names { fmt.Printf("%d: %q\n", i, name) } }
We create a date pattern with named groups for year, month, and day.
SubexpNames
returns these names in order. Index 0 is always empty.
Matching with Named Groups
This example shows how to use named groups with FindStringSubmatch
.
We can access matches by name or index.
package main import ( "fmt" "regexp" ) func main() { re := regexp.MustCompile(`(?P<first>\w+)\s+(?P<last>\w+)`) match := "John Doe" result := re.FindStringSubmatch(match) names := re.SubexpNames() for i, name := range names { if i != 0 && name != "" { fmt.Printf("%s: %s\n", name, result[i]) } } }
The pattern captures first and last names. We use SubexpNames
to
get group names and print the matched values with their names.
Accessing Named Groups Programmatically
We can create a map of named groups for easier access. This makes working with matches more convenient.
package main import ( "fmt" "regexp" ) func main() { re := regexp.MustCompile(`(?P<protocol>https?)://(?P<domain>[^/]+)/(?P<path>.*)`) url := "https://example.com/path/to/resource" match := re.FindStringSubmatch(url) names := re.SubexpNames() result := make(map[string]string) for i, name := range names { if i != 0 && name != "" { result[name] = match[i] } } fmt.Printf("Protocol: %s\n", result["protocol"]) fmt.Printf("Domain: %s\n", result["domain"]) fmt.Printf("Path: %s\n", result["path"]) }
We parse a URL into components using named groups. The map allows accessing parts by name instead of numeric index.
Mixed Named and Unnamed Groups
Patterns can mix named and unnamed groups. SubexpNames
shows empty
strings for unnamed groups.
package main import ( "fmt" "regexp" ) func main() { re := regexp.MustCompile(`(\w+)-(?P<middle>\w+)-(\w+)`) input := "first-middle-last" match := re.FindStringSubmatch(input) names := re.SubexpNames() for i, name := range names { if name == "" { name = fmt.Sprintf("unnamed%d", i) } fmt.Printf("%s: %s\n", name, match[i]) } }
The pattern has two unnamed groups and one named group. We handle unnamed groups by creating temporary names for display purposes.
Validating Group Names
This example checks if specific group names exist in the pattern before using them. This prevents runtime errors.
package main import ( "fmt" "regexp" ) func main() { re := regexp.MustCompile(`(?P<user>\w+)@(?P<domain>\w+\.\w+)`) email := "user@example.com" names := re.SubexpNames() required := []string{"user", "domain"} for _, name := range required { found := false for _, n := range names { if n == name { found = true break } } if !found { panic(fmt.Sprintf("missing required group: %s", name)) } } match := re.FindStringSubmatch(email) fmt.Printf("User: %s\n", match[1]) fmt.Printf("Domain: %s\n", match[2]) }
We verify that required group names exist in the pattern. This is useful when working with dynamically created regular expressions.
Reusing Group Names
When group names are reused in a pattern, SubexpNames
reflects
this. Each occurrence gets the same name.
package main import ( "fmt" "regexp" ) func main() { re := regexp.MustCompile(`(?P<digit>\d)(?P<digit>\d)`) input := "12" names := re.SubexpNames() match := re.FindStringSubmatch(input) for i, name := range names { if name != "" { fmt.Printf("%s: %s\n", name, match[i]) } } }
The pattern reuses the "digit" group name. Both digits are captured, but only the second appears in the results due to group numbering.
Complex Pattern with Multiple Groups
This example illustrates the use of SubexpNames
in conjunction with
a complex regular expression pattern that contains multiple named capturing
groups. Named groups allow developers to assign a descriptive name to each group
in a regular expression, making the patterns more readable and the extracted
data easier to interpret. The ability to label capturing groups is particularly
useful when working with structured data such as URLs, where each part (e.g.,
scheme, host, path) has a distinct meaning and needs to be extracted in an
organized manner.
package main import ( "fmt" "regexp" ) func main() { pattern := `^(?P<scheme>\w+)://` + `(?P<host>[^/:]+)` + `(?::(?P<port>\d+))?` + `(?P<path>/[^?]*)?` + `(?:\?(?P<query>[^#]*))?` + `(?:#(?P<fragment>.*))?$` re := regexp.MustCompile(pattern) url := "https://example.com:8080/path?query=value#frag" names := re.SubexpNames() match := re.FindStringSubmatch(url) for i, name := range names { if name != "" && i < len(match) { fmt.Printf("%-10s: %s\n", name, match[i]) } } }
The example defines a comprehensive pattern to parse a URL into its components:
scheme, host, port, path, query, and fragment. The pattern uses named groups
like ?P<scheme>
and ?P<host>
to label each
part of the URL, ensuring that the match results are meaningful and
self-explanatory. Once compiled using regexp.MustCompile
, the
regular expression is used to process the example URL,
"https://example.com:8080/path?query=value#frag"
, by applying the
FindStringSubmatch
function, which returns a slice containing the
full match and all capturing group matches.
The SubexpNames
method of the compiled regular expression is then
used to retrieve the names of all capturing groups in the pattern. This method
returns a slice where each element corresponds to the capturing group at the
same index in the match results. By iterating through the slice of names and
match results, the program prints the name of each capturing group along with
its matched value. The combination of SubexpNames
and
FindStringSubmatch
demonstrates how to efficiently work with named
groups to parse complex inputs and map each match to its corresponding label.
Source
Go regexp package documentation
This tutorial covered the Regexp.SubexpNames
method in Go with
practical examples of named capture group usage.
Author
List all Go tutorials.