String Utilities

Manipulate strings with Velocity's fluent string utilities for slugs, cases, truncation, and more.

Velocity provides a comprehensive string utilities package with powerful text manipulation functions inspired by popular web frameworks, offering fluent interfaces and lazy loading for optimal performance.

Quick Start

Two Ways to Use: String utilities work with both static functions and a fluent interface for method chaining.
import "github.com/velocitykode/velocity/pkg/str"

func main() {
    // Static functions - simple and direct
    result := str.Snake("HelloWorldExample")
    // Returns: "hello_world_example"

    // Case conversions
    camel := str.Camel("hello_world_example")    // "helloWorldExample"
    kebab := str.Kebab("HelloWorldExample")      // "hello-world-example"
    studly := str.Studly("hello_world_example")  // "HelloWorldExample"

    // String manipulation
    after := str.After("user@example.com", "@")  // "example.com"
    before := str.Before("user@example.com", "@") // "user"
    contains := str.Contains("Hello World", "World") // true
}
import "github.com/velocitykode/velocity/pkg/str"

func main() {
    // Fluent interface - chain multiple operations
    result := str.Of("  Hello World Example  ").
        Trim().                    // Remove whitespace
        Snake().                   // Convert to snake_case
        Upper().                   // Convert to uppercase
        String()                   // Get final string

    // Result: "HELLO_WORLD_EXAMPLE"

    // Complex transformation
    username := str.Of("  John Doe  ").
        Trim().
        Lower().
        Replace(" ", "_").
        String()
    // Result: "john_doe"
}

Case Conversion Functions

Snake Case: Convert strings to snake_case (lowercase with underscores)

str.Snake("HelloWorldExample")    // "hello_world_example"
str.Snake("camelCaseString")      // "camel_case_string"
str.Snake("kebab-case-string")    // "kebab_case_string"
str.Snake("Mixed String Types")   // "mixed_string_types"
Snake case is commonly used for variable names, database column names, and file names.

Camel Case: Convert strings to camelCase (first letter lowercase, subsequent words capitalized)

str.Camel("hello_world_example")  // "helloWorldExample"
str.Camel("kebab-case-string")    // "kebabCaseString"
str.Camel("Mixed String Types")   // "mixedStringTypes"
Camel case is the standard for JavaScript variables and Go field names when exported.

Kebab Case: Convert strings to kebab-case (lowercase with hyphens)

str.Kebab("HelloWorldExample")    // "hello-world-example"
str.Kebab("camelCaseString")      // "camel-case-string"
str.Kebab("hello_world_example")  // "hello-world-example"
Kebab case is commonly used for URL slugs, CSS class names, and HTML attributes.

Studly Case: Convert strings to StudlyCase/PascalCase (all words capitalized)

str.Studly("hello_world_example") // "HelloWorldExample"
str.Studly("camelCaseString")     // "CamelCaseString"
str.Studly("kebab-case-string")   // "KebabCaseString"
Studly case is used for Go struct names, class names, and other type definitions.

String Manipulation Functions

Extract Substrings

// Get text after a substring
str.After("user@example.com", "@")          // "example.com"
str.After("internal/handlers/UserHandler", "/") // "handlers/UserHandler"

// Get text before a substring
str.Before("user@example.com", "@")         // "user"
str.Before("path/to/file.txt", ".")         // "path/to/file"

// Get text between two substrings
str.Between("Hello [World] Test", "[", "]") // "World"
str.Between("<div>Content</div>", ">", "<") // "Content"

String Checks

// Check if string contains substring
str.Contains("Hello World", "World")        // true
str.Contains("Hello World", "world")        // false (case-sensitive)

// Check if string starts with substring
str.StartsWith("Hello World", "Hello")      // true
str.StartsWith("Hello World", "World")      // false

// Check if string ends with substring
str.EndsWith("Hello World", "World")        // true
str.EndsWith("Hello World", "Hello")        // false

// Check if string is empty
str.IsEmpty("")                             // true
str.IsEmpty("   ")                          // false (whitespace counts)

String Transformations

// Limit string to specified length
str.Limit("This is a long string", 10)      // "This is a..."
str.Limit("Short", 10)                      // "Short"

// Generate random string
str.Random(8)                               // "aB3kL9mP" (random)
str.Random(16)                              // 16 character random string

// Repeat string
str.Repeat("Hello", 3)                      // "HelloHelloHello"
str.Repeat("-=", 5)                         // "-=-=-=-=-="

// Replace all occurrences
str.Replace("Hello World World", "World", "Go") // "Hello Go Go"

// Reverse string
str.Reverse("Hello")                        // "olleH"
str.Reverse("12345")                        // "54321"

Fluent Interface (Stringable)

For method chaining, use the fluent interface:

import "github.com/velocitykode/velocity/pkg/str"

result := str.Of("  Hello World Example  ").
    Trim().                    // Remove whitespace
    Snake().                   // Convert to snake_case
    Upper().                   // Convert to uppercase
    String()                   // Get final string

// Result: "HELLO_WORLD_EXAMPLE"

Available Fluent Methods

s := str.Of("Hello World")

// Case conversions
s.Snake()                     // Chain snake_case conversion
s.Camel()                     // Chain camelCase conversion
s.Kebab()                     // Chain kebab-case conversion
s.Studly()                    // Chain StudlyCase conversion
s.Upper()                     // Chain uppercase conversion
s.Lower()                     // Chain lowercase conversion

// String manipulations
s.Trim()                      // Chain whitespace trimming
s.Replace("World", "Go")      // Chain replacement
s.After("@")                  // Chain after extraction
s.Before("@")                 // Chain before extraction
s.Limit(10)                   // Chain length limiting

// Get final result
finalString := s.String()     // Convert back to string

Lazy Loading & Performance

Important: Only the functions you actually use are compiled into your binary, keeping it lightweight and fast.

The string utilities package uses lazy loading to ensure optimal performance:

// Only the Snake function is compiled into your binary
result := str.Snake("HelloWorldExample")

Performance Benefits:

  • Reduced Binary Size: Only used functions are included
  • Fast Compilation: Unused code is eliminated
  • Optimal Performance: No overhead from unused features
  • Memory Efficient: Minimal memory footprint

Advanced Usage

Custom Delimiters

// Using custom separators in case conversion
str.ToDelimited("HelloWorldExample", "_")  // "hello_world_example"
str.ToDelimited("HelloWorldExample", "-")  // "hello-world-example"
str.ToDelimited("HelloWorldExample", ".")  // "hello.world.example"

Regex Pattern Caching

The package automatically caches compiled regex patterns for better performance:

// First call compiles and caches the regex
str.Snake("FirstString")

// Subsequent calls reuse the cached regex
str.Snake("SecondString")  // Faster execution
str.Snake("ThirdString")   // Even faster

Testing String Functions

func TestStringUtilities(t *testing.T) {
    // Test case conversions
    assert.Equal(t, "hello_world", str.Snake("HelloWorld"))
    assert.Equal(t, "helloWorld", str.Camel("hello_world"))
    assert.Equal(t, "hello-world", str.Kebab("HelloWorld"))

    // Test string manipulation
    assert.Equal(t, "example.com", str.After("user@example.com", "@"))
    assert.Equal(t, "user", str.Before("user@example.com", "@"))
    assert.True(t, str.Contains("Hello World", "World"))

    // Test fluent interface
    result := str.Of("  Hello World  ").Trim().Snake().String()
    assert.Equal(t, "hello_world", result)
}

Configuration

String utilities work without configuration, but you can customize behavior:

# Enable debug mode for string operations (optional)
STR_DEBUG=false

# Cache regex patterns (enabled by default)
STR_CACHE_REGEX=true

Best Practices

  1. Use Static Functions: For simple operations, use static functions like str.Snake()
  2. Use Fluent Interface: For complex transformations, chain operations with str.Of()
  3. Cache Results: Store frequently used transformations in variables
  4. Validate Input: Check for empty strings before processing
  5. Consider Unicode: The package handles UTF-8 correctly for international text

Examples

Processing user input for registration:

func processUsername(input string) string {
    return str.Of(input).
        Trim().                    // Remove whitespace
        Lower().                   // Normalize case
        Replace(" ", "_").         // Replace spaces
        Limit(20).                 // Limit length
        String()
}

username := processUsername("  John Doe  ")
// Result: "john_doe"
Perfect for cleaning user input while maintaining readability and enforcing length limits.

Generating API endpoints from model names:

func generateEndpoint(modelName string) string {
    return "/api/" + str.Snake(modelName)
}

endpoint := generateEndpoint("UserHandler")
// Result: "/api/user_handler"

// Multiple endpoints
endpoints := []string{
    generateEndpoint("ProductHandler"),  // "/api/product_handler"
    generateEndpoint("OrderHandler"),    // "/api/order_handler"
    generateEndpoint("CustomerHandler"), // "/api/customer_handler"
}
Automatically converts Go struct names to REST API conventions.

Sanitizing file names for safe storage:

func sanitizeFileName(name string) string {
    return str.Of(name).
        Replace(" ", "_").         // Replace spaces
        Snake().                   // Convert to snake_case
        Lower().                   // Lowercase
        String()
}

fileName := sanitizeFileName("My Important Document")
// Result: "my_important_document"

// Batch processing
files := []string{
    "User Profile Picture",
    "Invoice 2024-01",
    "Meeting Notes",
}

for _, file := range files {
    safe := sanitizeFileName(file)
    fmt.Printf("%s -> %s\n", file, safe)
}
Ensures file names are safe across different operating systems and file systems.