
A fluent, Laravel-inspired string toolkit for Go, focused on rune-safe helpers, expressive transformations, and predictable behavior beyond the standard library.
Installation
go get github.com/goforj/strRunnable examples
Every function has a corresponding runnable example under ./examples.
These examples are generated directly from the documentation blocks of each function, ensuring the docs and code never drift. These are the same examples you see here in the README and GoDoc.
An automated test executes every example to verify it builds and runs successfully.
This guarantees all examples are valid, up-to-date, and remain functional as the API evolves.
API Index
Affixes
ChopEnd
ChopEnd removes the first matching suffix if present.
v := str.Of("file.txt").ChopEnd(".txt", ".md").String()
println(v)
// #string fileChopStart
ChopStart removes the first matching prefix if present.
v := str.Of("https://goforj.dev").ChopStart("https://", "http://").String()
println(v)
// #string goforj.devEnsurePrefix
EnsurePrefix ensures the string starts with prefix, adding it if missing.
v := str.Of("path/to").EnsurePrefix("/").String()
println(v)
// #string /path/toEnsureSuffix
EnsureSuffix ensures the string ends with suffix, adding it if missing.
v := str.Of("path/to").EnsureSuffix("/").String()
println(v)
// #string path/to/Unwrap
Unwrap removes matching before and after strings if present.
v := str.Of(`"GoForj"`).Unwrap(`"`, `"`).String()
println(v)
// #string GoForjWrap
Wrap surrounds the string with before and after (after defaults to before).
v := str.Of("GoForj").Wrap(`"`, "").String()
println(v)
// #string "GoForj"Case
Camel
Camel converts the string to camelCase.
v := str.Of("foo_bar baz").Camel().String()
println(v)
// #string fooBarBazHeadline
Headline converts the string into a human-friendly headline: splits on case/underscores/dashes/whitespace, title-cases words, and lowercases small words (except the first).
v := str.Of("emailNotification_sent").Headline().String()
println(v)
// #string Email Notification SentKebab
Kebab converts the string to kebab-case.
v := str.Of("fooBar baz").Kebab().String()
println(v)
// #string foo-bar-bazLcFirst
LcFirst returns the string with the first rune lower-cased.
v := str.Of("Gopher").LcFirst().String()
fmt.Println(v)
// #string gopherPascal
Pascal converts the string to PascalCase.
v := str.Of("foo_bar baz").Pascal().String()
fmt.Println(v)
// #string FooBarBazSnake
Snake converts the string to snake_case using the provided separator (default "_").
v := str.Of("fooBar baz").Snake("_").String()
println(v)
// #string foo_bar_bazTitle
Title converts the string to title case (first letter of each word upper, rest lower) using Unicode rules.
v := str.Of("a nice title uses the correct case").Title().String()
println(v)
// #string A Nice Title Uses The Correct CaseToLower
ToLower returns a lowercase copy of the string using Unicode rules.
v := str.Of("GoLang").ToLower().String()
println(v)
// #string golangToTitle
ToTitle returns a title-cased copy where all letters are mapped using Unicode title case.
v := str.Of("ß").ToTitle().String()
println(v)
// #string SSToUpper
ToUpper returns an uppercase copy of the string using Unicode rules.
v := str.Of("GoLang").ToUpper().String()
println(v)
// #string GOLANGUcFirst
UcFirst returns the string with the first rune upper-cased.
v := str.Of("gopher").UcFirst().String()
println(v)
// #string GopherUcWords
UcWords uppercases the first rune of each word, leaving the rest unchanged. Words are sequences of letters/digits.
v := str.Of("hello WORLD").UcWords().String()
println(v)
// #string Hello WORLDChecks
IsASCII
IsASCII reports whether the string consists solely of 7-bit ASCII runes.
v := str.Of("gopher").IsASCII()
println(v)
// #bool trueIsBlank
IsBlank reports whether the string contains only Unicode whitespace.
v := str.Of(" \\t\\n")
println(v.IsBlank())
// #bool trueIsEmpty
IsEmpty reports whether the string has zero length.
v := str.Of("").IsEmpty()
println(v)
// #bool trueCleanup
Deduplicate
Deduplicate collapses consecutive instances of char into a single instance. If char is zero, space is used.
v := str.Of("The Go Playground").Deduplicate(' ').String()
println(v)
// #string The Go PlaygroundNormalizeNewlines
NormalizeNewlines replaces CRLF, CR, and Unicode separators with \n.
v := str.Of("a\\r\\nb\\u2028c").NormalizeNewlines().String()
println(v)
// #string a\nb\ncNormalizeSpace
NormalizeSpace collapses whitespace runs to single spaces without trimming ends.
v := str.Of(" go forj ").NormalizeSpace().String()
println(v)
// #string go forjSquish
Squish trims leading/trailing whitespace and collapses internal whitespace to single spaces.
v := str.Of(" go forj ").Squish().String()
println(v)
// #string go forjTrim
Trim trims leading and trailing characters. If cutset is the zero value (empty string), trims Unicode whitespace.
v := str.Of(" GoForj ").Trim("").String()
println(v)
// #string GoForjTrimLeft
TrimLeft trims leading characters. If cutset is the zero value (empty string), trims Unicode whitespace.
v := str.Of(" GoForj ").TrimLeft("").String()
println(v)
// #string GoForjTrimRight
TrimRight trims trailing characters. If cutset is the zero value (empty string), trims Unicode whitespace.
v := str.Of(" GoForj ").TrimRight("").String()
println(v)
// #string GoForjTrimSpace
TrimSpace trims leading and trailing Unicode whitespace.
v := str.Of(" GoForj ").TrimSpace().String()
println(v)
// #string GoForjComparison
Equals
Equals reports whether the string exactly matches other (case-sensitive).
v := str.Of("gopher").Equals("gopher")
println(v)
// #bool trueEqualsFold
EqualsFold reports whether the string matches other using Unicode case folding.
v := str.Of("gopher").EqualsFold("GOPHER")
println(v)
// #bool trueCompose
Append
Append concatenates the provided parts to the end of the string.
v := str.Of("Go").Append("Forj", "!").String()
println(v)
// #string GoForj!NewLine
NewLine appends a newline character to the string.
v := str.Of("hello").NewLine().Append("world").String()
println(v)
// #string hello\nworldPrepend
Prepend concatenates the provided parts to the beginning of the string.
v := str.Of("World").Prepend("Hello ", "Go ").String()
println(v)
// #string Hello Go WorldConstructor
Of
Of wraps a raw string with fluent helpers.
v := str.Of("gopher")
println(v.String())
// #string gopherEncoding
FromBase64
FromBase64 decodes a standard Base64 string.
v, err := str.Of("Z29waGVy").FromBase64()
println(v.String(), err)
// #string gopher
// #error <nil>ToBase64
ToBase64 encodes the string using standard Base64.
v := str.Of("gopher").ToBase64().String()
println(v)
// #string Z29waGVyFluent
GoString
GoString allows %#v formatting to print the raw string.
v := str.Of("go")
println(fmt.Sprintf("%#v", v))
// #string goString
String returns the underlying raw string value.
v := str.Of("go").String()
println(v)
// #string goLength
Len
Len returns the number of runes in the string.
v := str.Of("gophers 🦫").Len()
println(v)
// #int 9RuneCount
RuneCount is an alias for Len to make intent explicit in mixed codebases.
v := str.Of("naïve").RuneCount()
println(v)
// #int 5Masking
Mask
Mask replaces the middle of the string with the given rune, revealing revealLeft runes at the start and revealRight runes at the end. Negative reveal values count from the end. If the reveal counts cover the whole string, the original string is returned.
v := str.Of("gopher@example.com").Mask('*', 3, 4).String()
println(v)
// #string gop***********.comMatch
Is
Is reports whether the string matches any of the provided wildcard patterns. Patterns use '*' as a wildcard. Case-sensitive.
v := str.Of("foo/bar").Is("foo/*")
println(v)
// #bool trueIsMatch
IsMatch reports whether the string matches the provided regular expression.
v := str.Of("abc123").IsMatch(regexp.MustCompile(`\d+`))
println(v)
// #bool trueMatch
Match returns the first match and submatches for the pattern.
re := regexp.MustCompile(`g(o+)`)
v := str.Of("gooo").Match(re)
println(v)
// #[]string [gooo ooo]MatchAll
MatchAll returns all matches and submatches for the pattern.
re := regexp.MustCompile(`go+`)
v := str.Of("go gopher gooo").MatchAll(re)
println(v)
// #[][]string [[go] [gooo]]Padding
PadBoth
PadBoth pads the string on both sides to reach length runes using pad (defaults to space).
v := str.Of("go").PadBoth(6, "-").String()
println(v)
// #string --go--PadLeft
PadLeft pads the string on the left to reach length runes using pad (defaults to space).
v := str.Of("go").PadLeft(5, " ").String()
println(v)
// #string \u00a0\u00a0\u00a0goPadRight
PadRight pads the string on the right to reach length runes using pad (defaults to space).
v := str.Of("go").PadRight(5, ".").String()
println(v)
// #string go...Pluralize
Plural
Plural returns a best-effort English plural form of the last word.
v := str.Of("city").Plural().String()
println(v)
// #string citiesSingular
Singular returns a best-effort English singular form of the last word.
v := str.Of("people").Singular().String()
println(v)
// #string personReplace
Remove
Remove deletes all occurrences of provided substrings.
v := str.Of("The Go Toolkit").Remove("Go ").String()
println(v)
// #string The ToolkitReplaceAll
ReplaceAll replaces all occurrences of old with new in the string. If old is empty, the original string is returned unchanged.
v := str.Of("go gopher go").ReplaceAll("go", "Go").String()
println(v)
// #string Go Gopher GoReplaceArray
ReplaceArray replaces all occurrences of each old in olds with repl.
v := str.Of("The---Go---Toolkit")
println(v.ReplaceArray([]string{"---"}, "-").String())
// #string The-Go-ToolkitReplaceEnd
ReplaceEnd replaces old with repl at the end of the string, if present.
v := str.Of("file.old").ReplaceEnd(".old", ".new").String()
println(v)
// #string file.newReplaceFirst
ReplaceFirst replaces the first occurrence of old with repl.
v := str.Of("gopher gopher").ReplaceFirst("gopher", "go").String()
println(v)
// #string go gopherReplaceFirstFold
ReplaceFirstFold replaces the first occurrence of old with repl using Unicode case folding.
v := str.Of("go gopher GO").ReplaceFirstFold("GO", "Go").String()
println(v)
// #string Go gopher GOReplaceFold
ReplaceFold replaces all occurrences of old with repl using Unicode case folding.
v := str.Of("go gopher GO").ReplaceFold("GO", "Go").String()
println(v)
// #string Go Gopher GoReplaceLast
ReplaceLast replaces the last occurrence of old with repl.
v := str.Of("gopher gopher").ReplaceLast("gopher", "go").String()
println(v)
// #string gopher goReplaceLastFold
ReplaceLastFold replaces the last occurrence of old with repl using Unicode case folding.
v := str.Of("go gopher GO").ReplaceLastFold("GO", "Go").String()
println(v)
// #string go gopher GoReplaceMatches
ReplaceMatches applies repl to each regex match and returns the result.
re := regexp.MustCompile(`\d+`)
v := str.Of("Hello 123 World").ReplaceMatches(re, func(m string) string { return "[" + m + "]" }).String()
println(v)
// #string Hello [123] WorldReplaceStart
ReplaceStart replaces old with repl at the start of the string, if present.
v := str.Of("prefix-value").ReplaceStart("prefix-", "new-").String()
println(v)
// #string new-valueSwap
Swap replaces multiple values using strings.Replacer built from a map.
pairs := map[string]string{"Gophers": "GoForj", "are": "is", "great": "fantastic"}
v := str.Of("Gophers are great!").Swap(pairs).String()
println(v)
// #string GoForj is fantastic!Search
Contains
Contains reports whether the string contains any of the provided substrings (case-sensitive). Empty substrings return true to match strings.Contains semantics.
v := str.Of("Go means gophers").Contains("rust", "gopher")
println(v)
// #bool trueContainsAll
ContainsAll reports whether the string contains all provided substrings (case-sensitive). Empty substrings are ignored.
v := str.Of("Go means gophers").ContainsAll("Go", "gopher")
println(v)
// #bool trueContainsAllFold
ContainsAllFold reports whether the string contains all provided substrings, using Unicode case folding for comparisons. Empty substrings are ignored.
v := str.Of("Go means gophers").ContainsAllFold("go", "GOPHER")
println(v)
// #bool trueContainsFold
ContainsFold reports whether the string contains any of the provided substrings, using Unicode case folding for comparisons. Empty substrings return true.
v := str.Of("Go means gophers").ContainsFold("GOPHER", "rust")
println(v)
// #bool trueCount
Count returns the number of non-overlapping occurrences of sub.
v := str.Of("gogophergo").Count("go")
println(v)
// #int 3EndsWith
EndsWith reports whether the string ends with any of the provided suffixes (case-sensitive).
v := str.Of("gopher").EndsWith("her", "cat")
println(v)
// #bool trueEndsWithFold
EndsWithFold reports whether the string ends with any of the provided suffixes using Unicode case folding.
v := str.Of("gopher").EndsWithFold("HER")
println(v)
// #bool trueIndex
Index returns the rune index of the first occurrence of sub, or -1 if not found.
v := str.Of("héllo").Index("llo")
println(v)
// #int 2LastIndex
LastIndex returns the rune index of the last occurrence of sub, or -1 if not found.
v := str.Of("go gophers go").LastIndex("go")
println(v)
// #int 10StartsWith
StartsWith reports whether the string starts with any of the provided prefixes (case-sensitive).
v := str.Of("gopher").StartsWith("go", "rust")
println(v)
// #bool trueStartsWithFold
StartsWithFold reports whether the string starts with any of the provided prefixes using Unicode case folding.
v := str.Of("gopher").StartsWithFold("GO")
println(v)
// #bool trueSlug
Slug
Slug produces an ASCII slug using the provided separator (default "-"), stripping accents where possible. Not locale-aware; intended for identifiers/URLs.
v := str.Of("Go Forj Toolkit").Slug("-").String()
println(v)
// #string go-forj-toolkitSnippet
Excerpt
Excerpt returns a snippet around the first occurrence of needle with the given radius. If needle is not found, an empty string is returned. If radius <= 0, a default of 100 is used. Omission is used at the start/end when text is trimmed (default "...").
v := str.Of("This is my name").Excerpt("my", 3, "...")
println(v.String())
// #string ...is my na...Split
Lines
Lines splits the string into lines after normalizing newline variants.
v := str.Of("a\\r\\nb\\nc").Lines()
println(v)
// #[]string [a b c]Split
Split splits the string by the given separator.
v := str.Of("a,b,c").Split(",")
println(v)
// #[]string [a b c]UcSplit
UcSplit splits the string on uppercase boundaries and delimiters, returning segments.
v := str.Of("HTTPRequestID").UcSplit()
println(v)
// #[]string [HTTP Request ID]Substrings
After
After returns the substring after the first occurrence of sep. If sep is empty or not found, the original string is returned.
v := str.Of("gopher::go").After("::").String()
println(v)
// #string goAfterLast
AfterLast returns the substring after the last occurrence of sep. If sep is empty or not found, the original string is returned.
v := str.Of("pkg/path/file.txt").AfterLast("/").String()
println(v)
// #string file.txtBefore
Before returns the substring before the first occurrence of sep. If sep is empty or not found, the original string is returned.
v := str.Of("gopher::go").Before("::").String()
println(v)
// #string gopherBeforeLast
BeforeLast returns the substring before the last occurrence of sep. If sep is empty or not found, the original string is returned.
v := str.Of("pkg/path/file.txt").BeforeLast("/").String()
println(v)
// #string pkg/pathBetween
Between returns the substring between the first occurrence of start and the last occurrence of end. Returns an empty string if either marker is missing or overlapping.
v := str.Of("This is my name").Between("This", "name").String()
println(v)
// #string is myBetweenFirst
BetweenFirst returns the substring between the first occurrence of start and the first occurrence of end after it. Returns an empty string if markers are missing.
v := str.Of("[a] bc [d]").BetweenFirst("[", "]").String()
println(v)
// #string aCharAt
CharAt returns the rune at the given index and true if within bounds.
v, ok := str.Of("gopher").CharAt(2)
println(string(v), ok)
// #string p
// #bool trueLimit
Limit truncates the string to length runes, appending suffix if truncation occurs.
v := str.Of("Perfectly balanced, as all things should be.").Limit(10, "...").String()
println(v)
// #string Perfectly...Slice
Slice returns the substring between rune offsets [start:end). Indices are clamped; if start >= end the result is empty.
v := str.Of("naïve café").Slice(3, 7).String()
println(v)
// #string e caSubstrReplace
SubstrReplace replaces the rune slice in [start:end) with repl.
v := str.Of("naïve café").SubstrReplace("i", 2, 3).String()
println(v)
// #string naive caféTake
Take returns the first length runes of the string (clamped).
v := str.Of("gophers").Take(3).String()
println(v)
// #string gopTakeLast
TakeLast returns the last length runes of the string (clamped).
v := str.Of("gophers").TakeLast(4).String()
println(v)
// #string hersTransform
Repeat
Repeat repeats the string count times (non-negative).
v := str.Of("go").Repeat(3).String()
println(v)
// #string gogogoReverse
Reverse returns a rune-safe reversed string.
v := str.Of("naïve").Reverse().String()
println(v)
// #string evïanTransliterate
Transliterate replaces a small set of accented runes with ASCII equivalents.
v := str.Of("café déjà vu").Transliterate().String()
println(v)
// #string cafe deja vuWords
FirstWord
FirstWord returns the first word token or empty string.
v := str.Of("Hello world")
println(v.FirstWord().String())
// #string HelloJoin
Join joins the provided words with sep.
v := str.Of("unused").Join([]string{"foo", "bar"}, "-").String()
println(v)
// #string foo-barLastWord
LastWord returns the last word token or empty string.
v := str.Of("Hello world").LastWord().String()
println(v)
// #string worldSplitWords
SplitWords splits the string into words (Unicode letters/digits runs).
v := str.Of("one, two, three").SplitWords()
println(v)
// #[]string [one two three]WordCount
WordCount returns the number of word tokens (letters/digits runs).
v := str.Of("Hello, world!").WordCount()
println(v)
// #int 2Words
Words limits the string to count words, appending suffix if truncated.
v := str.Of("Perfectly balanced, as all things should be.").Words(3, " >>>").String()
println(v)
// #string Perfectly balanced as >>>WrapWords
WrapWords wraps the string to the given width on word boundaries, using breakStr between lines.
v := str.Of("The quick brown fox jumped over the lazy dog.").WrapWords(20, "\n").String()
println(v)
// #string The quick brown fox\njumped over the lazy\ndog.