In Go's regexp package, how do you turn on case-insensitive or dot-matches-newline matching?
answer
- there is no second argument to Compile
- the mode lives inside the pattern text
- four letters: i, m, s, U
- a bare flag group runs to the end of its group
- the colon form scopes it to one group
basics
~20 sPut the flag inside the pattern text: (?i) for case-insensitive, (?s) to let . match a newline. Go's regexp has no flags argument, so (?i), (?m), (?s) and (?U) written in the pattern are the only way to set modes.
solid answer
~40 sGo's `regexp` takes only a pattern string — there is no flags parameter — so modes are written into the pattern itself. `(?i)` makes matching case-insensitive, `(?s)` makes `.` match a newline (it does not by default), `(?m)` makes `^` and `$` match at line boundaries instead of only at the ends of the text, and `(?U)` swaps greedy and non-greedy repetition. A flag written as `(?i)` applies from that point to the end of the enclosing group, so `(?i)` at the front of the pattern covers everything; `(?i:abc)` scopes it to just that group, and `(?-i)` turns it back off. Flags combine in one group: `(?is)`. Because they live in the pattern string, a rule file can carry its own modes without the code that compiles it knowing anything about them.
code
go · 5 lines// case-insensitive, and . also matches newlines
block := regexp.MustCompile(`(?is)^begin.*end$`)
// only the word hello is case-insensitive here
greet := regexp.MustCompile(`(?i:hello) World`)go deeper
Remember that modes are written inside the pattern: (?i) for ignoring case and (?s) so . can cross a newline. Knowing there is no flags argument on the compile call is the key recall here.
Explain scoping precisely: a bare flag group runs to the end of the enclosing group, the (?i:...) form is limited to that group, and (?-i) clears it. Also state the defaults for ., ^ and $.
Show you treat missing flags as a review item when rules are ported: a lost mode still compiles and simply stops matching, which is far quieter than an unsupported construct and needs fixture tests rather than a compile check to catch.
Decide how rules are authored and stored across teams: whether modes must be written into the pattern text, whether fragments are required to use scoped flag groups, and what the review standard is for patterns that arrive from an external dialect.
Most regex APIs take the pattern and a set of flags: Java passes `Pattern.CASE_INSENSITIVE`, JavaScript appends `i` after the closing slash, Python passes `re.I`. Go's `regexp` package does not. `regexp.Compile` and `regexp.MustCompile` take a single string, and every mode is expressed inside the pattern with an inline flag group. ## The four flags | Flag | Meaning | Default | |---|---|---| | `i` | case-insensitive | off | | `m` | multi-line: `^` and `$` match at line boundaries | off | | `s` | let `.` match a newline | off | | `U` | ungreedy: swap the meaning of `x*` and `x*?` | off | The defaults matter as much as the flags. Without `s`, `.` matches any rune **except** a newline, so a pattern meant to span a multi-line block silently matches nothing. Without `m`, `^` matches only at the beginning of the whole text and `$` only at the very end — and Go's `$` is strict: it does not also match just before a trailing newline the way some engines do. Combining them, `(?sm)` is common when scanning a document where you want both line anchors and a dot that crosses lines. ## Two syntaxes, two scopes There are two ways to write a flag group. **`(?flags)`** is a setting that takes effect at that point and continues to the end of the enclosing group (or the end of the pattern if it is not inside one). `(?i)abc` is case-insensitive throughout. `x(?i)yz` matches `x` case-sensitively and `yz` insensitively. `(a(?i)b)c` turns the flag on for `b` and, because the group closes, `c` is matched case-sensitively again. **`(?flags:re)`** is a non-capturing group with the flags applied only to `re`. `(?i:hello) World` matches `HELLO World` but not `hello world`. This form is the one to prefer when you are composing a pattern out of fragments, because it cannot leak a mode into the text that follows. A minus sign turns flags off: `(?-i)` from here on, `(?-s:...)` for one group, and `(?i-s:...)` sets one and clears another in the same group. ## Why Go chose this Inline flags are part of the pattern's own text, which means a pattern is fully self-describing. A rule stored in a config file, a database column or a command-line argument carries its own modes with it, and the Go code that compiles it does not need a parallel channel for "and this one is case-insensitive". It also means a fragment pasted into a larger pattern keeps its behaviour, provided the scoped `(?i:...)` form was used. The trade-off is that when you port a rule from an engine where flags live outside the pattern, the modes are exactly the part that gets lost. A pattern that ran with a case-insensitive flag elsewhere arrives in Go as a bare string and silently becomes case-sensitive — it compiles, it runs, it just stops matching things it used to. That is a quieter failure than an unsupported construct, which at least refuses to compile. ## Case-insensitivity is Unicode-aware `(?i)` folds case using Unicode simple case folding, not an ASCII lowercase. That means it matches across scripts that have case, and it is not the same thing as lowercasing the input yourself. It also costs a little at match time, because the compiled character classes grow to include the folded alternatives. ## Things that are not flags in Go There is no verbose or extended mode that lets you write a pattern across several lines with comments; if you want that, build the string with Go string concatenation or a raw string literal and keep the comments in the surrounding code. There is no global flag, because "find one" and "find all" are different methods rather than a mode. And there is no way to switch a pattern to case-insensitive after it is compiled — you compile a different pattern. ## Practical shape Write the flag once at the front for a whole-pattern mode, use the scoped form when only part of the pattern needs it, and prefer a raw string literal so backslashes stay readable: `regexp.MustCompile(`(?is)^begin.*end$`)` When you are reviewing a ported rule, check the flags before anything else: they do not announce themselves, and their absence is the difference between a rule that fires and a rule that quietly never does.
- What is the difference between `(?i)abc` and `(?i:abc)` in a Go pattern?`(?i)abc` switches case-insensitivity on at that point and leaves it on to the end of the enclosing group, so anything written after `abc` inherits it. `(?i:abc)` is a non-capturing group that applies the flag to `abc` only, and the mode reverts when the group closes. Use the scoped form when composing a pattern from fragments.
- A pattern that matched a multi-line block in another engine matches nothing in Go. What would you check first?The flags. In Go, `.` does not match a newline unless the pattern carries `(?s)`, and `^`/`$` anchor to the whole text unless it carries `(?m)`. When a rule is ported from an engine where flags are passed alongside the pattern, the flags are exactly what fails to travel, and the pattern still compiles cleanly.
- Is `(?i)` the same as lowercasing both the pattern and the input?No. `(?i)` applies Unicode simple case folding inside the matcher, so it handles scripts and characters that a naive ASCII lowercase would not, and it leaves the input untouched so match offsets still refer to the original text. Lowercasing the input also destroys information you may need from the match.
saying these in an interview costs you the question
- Says you pass a flags constant as a second argument to Compile
- Thinks Go's dot matches newlines by default
- Assumes $ also matches just before a trailing newline
- Believes a bare (?i) applies only to the next character
- Claims you can switch modes on an already-compiled Regexp