# Filter Package for String Manipulation: Complete Guide to StringFilter in Go

> Explore Go's StringFilter for powerful string manipulation. Discover 9 matching options: exact, regex, prefix, suffix, empty/non-empty, and sequential rule evaluation.

- Repository: [Aperture Robotics/util](https://github.com/aperturerobotics/util)
- Tags: tutorial
- Published: 2026-02-25

---

**The `filter` package provides a versatile `StringFilter` type that supports nine distinct string matching options—including exact value matching, regex patterns, prefix/suffix checks, and empty/non-empty validation—with all non-zero rules evaluated sequentially in the `CheckMatch` method.**

The `filter` package for string manipulation in the [aperturerobotics/util](https://github.com/aperturerobotics/util) repository offers a robust solution for conditional string matching through its `StringFilter` struct. Defined in [`filter/filter.pb.go`](https://github.com/aperturerobotics/util/blob/main/filter/filter.pb.go) and implemented in [`filter/filter.go`](https://github.com/aperturerobotics/util/blob/main/filter/filter.go), this type enables developers to define complex filtering rules using combinations of exact matches, regular expressions, and substring operations.

## StringFilter Options Overview

The `StringFilter` struct provides nine distinct fields for string manipulation and matching. When using `CheckMatch`, all non-zero rules must be satisfied for a match to succeed, while an empty filter matches any value.

| Option | Description | Implementation |
|--------|-------------|----------------|
| **Empty** | Matches only empty strings (`""`). | [`filter/filter.go`](https://github.com/aperturerobotics/util/blob/main/filter/filter.go) lines 26-28 |
| **NotEmpty** | Matches any non-empty string. | [`filter/filter.go`](https://github.com/aperturerobotics/util/blob/main/filter/filter.go) lines 29-31 |
| **Value** | Exact match with a single string. | [`filter/filter.go`](https://github.com/aperturerobotics/util/blob/main/filter/filter.go) lines 32-34 |
| **Values** | Matches if string equals any provided value. | [`filter/filter.go`](https://github.com/aperturerobotics/util/blob/main/filter/filter.go) lines 35-37 |
| **Re** | Regular expression pattern matching. | [`filter/filter.go`](https://github.com/aperturerobotics/util/blob/main/filter/filter.go) lines 38-47 |
| **HasPrefix** | Checks if string starts with given prefix. | [`filter/filter.go`](https://github.com/aperturerobotics/util/blob/main/filter/filter.go) lines 48-52 |
| **HasSuffix** | Checks if string ends with given suffix. | [`filter/filter.go`](https://github.com/aperturerobotics/util/blob/main/filter/filter.go) lines 53-57 |
| **Contains** | Checks if string contains given substring. | [`filter/filter.go`](https://github.com/aperturerobotics/util/blob/main/filter/filter.go) lines 58-62 |

## Detailed Filtering Capabilities

### Empty and Non-Empty Validation

The `Empty` and `NotEmpty` fields provide basic validation for string length. In [`filter/filter.go`](https://github.com/aperturerobotics/util/blob/main/filter/filter.go) lines 26-31, `CheckMatch` first evaluates whether the input string is empty or non-empty based on these boolean flags.

```go
// Match only empty strings
emptyFilter := &filter.StringFilter{
    Empty: true,
}

// Match any non-empty string
notEmptyFilter := &filter.StringFilter{
    NotEmpty: true,
}

```

### Exact Value Matching

For precise string comparison, use the `Value` field for single exact matches or `Values` for matching against multiple allowed strings. According to lines 32-37 in [`filter/filter.go`](https://github.com/aperturerobotics/util/blob/main/filter/filter.go), the implementation checks `Value` first, then iterates through the `Values` slice if provided.

```go
// Single exact match
exactFilter := &filter.StringFilter{
    Value: "production",
}

// Multiple allowed values
multiFilter := &filter.StringFilter{
    Values: []string{"staging", "production", "development"},
}

```

### Regex Pattern Matching

The `Re` field accepts regular expression patterns for complex string manipulation. As implemented in [`filter/filter.go`](https://github.com/aperturerobotics/util/blob/main/filter/filter.go) lines 38-47, the regex is compiled during the check and applied to the input string. The `Validate` method (lines 11-18) pre-checks regex syntax to prevent runtime compilation errors.

```go
// Date pattern matching (YYYY-MM-DD)
dateFilter := &filter.StringFilter{
    Re: `^\d{4}-\d{2}-\d{2}$`,
}

// Email domain validation
emailFilter := &filter.StringFilter{
    Re: `.*@example\.com$`,
}

```

### Prefix, Suffix, and Substring Checks

For substring operations, `StringFilter` provides three dedicated fields: `HasPrefix`, `HasSuffix`, and `Contains`. The implementation in [`filter/filter.go`](https://github.com/aperturerobotics/util/blob/main/filter/filter.go) lines 48-62 processes these checks sequentially using standard Go string functions.

```go
// File extension check
logFilter := &filter.StringFilter{
    HasSuffix: ".log",
}

// API version prefix
apiFilter := &filter.StringFilter{
    HasPrefix: "/v1/",
}

// Error message detection
errorFilter := &filter.StringFilter{
    Contains: "error",
}

```

## How CheckMatch Evaluates Filters

The `CheckMatch` method in [`filter/filter.go`](https://github.com/aperturerobotics/util/blob/main/filter/filter.go) (lines 21-64) implements a specific evaluation order for string manipulation:

1. **Nil filter** → returns `true` (matches any value)
2. **Empty/NotEmpty** → validates string length
3. **Value/Values** → checks exact matches
4. **Re** → compiles and applies regex pattern
5. **HasPrefix/HasSuffix/Contains** → performs substring checks

All non-zero rules must pass for the method to return `true`. An empty `StringFilter` (all fields zero) matches any input string.

## Validation and Error Handling

Before applying filters in production, use the `Validate` method (lines 11-18 in [`filter/filter.go`](https://github.com/aperturerobotics/util/blob/main/filter/filter.go)) to ensure regular expressions compile correctly:

```go
filter := &filter.StringFilter{
    Re: `[invalid regex(`,
}

if err := filter.Validate(); err != nil {
    // Handle compilation error
    log.Fatal(err)
}

```

This prevents runtime panics when `CheckMatch` attempts to compile the regex pattern.

## Practical Code Examples

Here is a comprehensive example demonstrating multiple filtering options for string manipulation:

```go
package main

import (
	"fmt"

	"github.com/aperturerobotics/util/filter"
)

func main() {
	// 1. Exact value match
	exact := &filter.StringFilter{
		Value: "golang",
	}
	fmt.Println(exact.CheckMatch("golang")) // → true
	fmt.Println(exact.CheckMatch("go"))     // → false

	// 2. Multiple allowed values
	anyOf := &filter.StringFilter{
		Values: []string{"apple", "banana", "cherry"},
	}
	fmt.Println(anyOf.CheckMatch("banana")) // → true
	fmt.Println(anyOf.CheckMatch("orange")) // → false

	// 3. Regex + prefix + suffix
	reg := &filter.StringFilter{
		Re:        `^\d{4}-\d{2}-\d{2}$`, // date format YYYY-MM-DD
		HasPrefix: "202",
		HasSuffix: "01",
	}
	fmt.Println(reg.CheckMatch("2023-01-01")) // → true
	fmt.Println(reg.CheckMatch("2023-02-01")) // → false (suffix mismatch)

	// 4. Contains and non-empty enforcement
	contains := &filter.StringFilter{
		NotEmpty: true,
		Contains: "error",
	}
	fmt.Println(contains.CheckMatch("fatal error occurred")) // → true
	fmt.Println(contains.CheckMatch(""))                    // → false (empty string)
}

```

## Summary

- The **filter package for string manipulation** provides nine distinct matching options through the `StringFilter` type.
- **Empty** and **NotEmpty** validate string length, while **Value** and **Values** enforce exact matches.
- **Re** enables regular expression patterns, and **HasPrefix**, **HasSuffix**, and **Contains** provide substring operations.
- The `CheckMatch` method in [`filter/filter.go`](https://github.com/aperturerobotics/util/blob/main/filter/filter.go) evaluates all non-zero rules sequentially, requiring all to pass for a successful match.
- Use the `Validate` method to pre-check regular expression syntax before runtime execution.

## Frequently Asked Questions

### What is the difference between Value and Values in StringFilter?

The `Value` field accepts a single string for exact matching, while the `Values` field accepts a slice of strings and matches if the input equals any element in that slice. According to [`filter/filter.go`](https://github.com/aperturerobotics/util/blob/main/filter/filter.go) lines 32-37, `CheckMatch` checks `Value` first, then iterates through `Values` if the single value check fails or is not set.

### How does StringFilter handle regular expression compilation errors?

The `Validate` method in [`filter/filter.go`](https://github.com/aperturerobotics/util/blob/main/filter/filter.go) lines 11-18 pre-compiles the regular expression specified in the `Re` field to verify syntax correctness. If compilation fails, `Validate` returns an error, allowing developers to catch malformed patterns before calling `CheckMatch`, which would otherwise attempt compilation during execution.

### Can I combine multiple filtering options in a single StringFilter?

Yes, you can set multiple fields simultaneously in a `StringFilter`. The `CheckMatch` method evaluates all non-zero rules in sequence: Empty/NotEmpty, Value/Values, Re, and finally HasPrefix/HasSuffix/Contains. For a match to succeed, the input string must satisfy every active constraint according to the logic in [`filter/filter.go`](https://github.com/aperturerobotics/util/blob/main/filter/filter.go) lines 21-64.

### What happens if StringFilter is nil or has no fields set?

A nil `StringFilter` always returns `true` from `CheckMatch`, effectively matching any value. Similarly, an empty `StringFilter` instance (where all fields remain at their zero values) also matches any input string. This behavior, implemented in [`filter/filter.go`](https://github.com/aperturerobotics/util/blob/main/filter/filter.go) lines 21-25, provides a safe default when filters are optional in your application configuration.