Question
How can I check whether one string contains another string in Go?
For example, I want behavior similar to this:
someString.contains("something")
What is the correct Go approach for testing whether a string includes a substring?
Short Answer
By the end of this page, you will understand how to check whether a string contains a substring in Go using the standard library. You will also learn the required syntax, how it behaves with case sensitivity, how developers use it in real code, and what mistakes beginners often make.
Concept
In Go, strings do not have methods like contains() attached directly to them. Instead, Go puts many string-related operations in the standard library package strings.
To check whether one string appears inside another, you use:
strings.Contains(s, substr)
It returns a bool:
trueifsubstrexists anywhere insidesfalseif it does not
Example:
strings.Contains("hello world", "world") // true
This matters because substring checks are common in real programs:
- validating user input
- checking file paths or URLs
- filtering logs
- inspecting API responses
- detecting keywords in text
Go's design prefers simple, explicit functions from packages over attaching many methods to built-in types. That is why you use strings.Contains instead of someString.contains(...).
Mental Model
Think of a string as a long line of text, and a substring as a smaller piece of paper with text written on it.
strings.Contains answers this question:
- "Can I find this small piece of text somewhere inside the larger line of text?"
If the larger text is:
"golang is fun"
and the smaller text is:
"is"
then the answer is true because that sequence of characters appears inside the larger string.
It is like searching for a word inside a sentence.
Syntax and Examples
Core syntax
strings.Contains(fullString, subString)
You must import the strings package:
import "strings"
Basic example
package main
import (
"fmt"
"strings"
)
func main() {
text := "I am learning Go"
fmt.Println(strings.Contains(text, "Go")) // true
fmt.Println(strings.Contains(text, "Python")) // false
}
Explanation
textis the main string."Go"is searched insidetext.- Since
"Go"exists in"I am learning Go", the result istrue. "Python"does not exist there, so the result isfalse.
Example in an if statement
package main
import (
"fmt"
"strings"
)
func main() {
email := "user@example.com"
if strings.Contains(email, "@") {
fmt.Println("Looks like an email address")
} else {
fmt.Println("Missing @ symbol")
}
}
This is a common pattern when validating or inspecting text.
Case sensitivity example
package main
import (
"fmt"
"strings"
)
func main() {
fmt.Println(strings.Contains("GoLang", "Go")) // true
fmt.Println(strings.Contains("GoLang", "go")) // false
}
strings.Contains is case-sensitive.
Case-insensitive check
package main
import (
"fmt"
"strings"
)
func main() {
text := "GoLang"
sub := "go"
result := strings.Contains(strings.ToLower(text), strings.ToLower(sub))
fmt.Println(result) // true
}
A common approach is to convert both strings to the same case first.
Step by Step Execution
Consider this code:
package main
import (
"fmt"
"strings"
)
func main() {
message := "backend-api-server"
found := strings.Contains(message, "api")
fmt.Println(found)
}
Step-by-step
1. Import packages
import (
"fmt"
"strings"
)
fmtis used to print output.stringsprovides substring functions.
2. Create the main string
message := "backend-api-server"
The variable message now stores that full text.
3. Search for the substring
found := strings.Contains(message, "api")
Go checks whether the characters "api" appear in "backend-api-server".
They do appear, so:
found = true
4. Print the result
fmt.Println(found)
The output is:
true
Another trace
fmt.Println(strings.Contains("banana", "nan")) // true
Why?
- Go scans the string
"banana" - It finds the sequence
"nan" - So the function returns
true
Real World Use Cases
Input validation
Check whether a user entered required symbols or keywords.
strings.Contains(password, "#")
strings.Contains(email, "@")
URL and route checks
Detect whether a request path contains a certain section.
strings.Contains(path, "/admin")
Log filtering
Search log messages for error words.
strings.Contains(logLine, "ERROR")
File processing
Check whether a filename includes an extension or naming pattern.
strings.Contains(fileName, ".csv")
API response inspection
Quickly inspect text responses for expected markers.
strings.Contains(responseBody, "success")
Content moderation or keyword detection
Detect blocked words or target phrases inside submitted text.
strings.Contains(comment, bannedWord)
Real Codebase Usage
In real Go projects, strings.Contains is often used as a small building block inside larger logic.
Guard clauses
Developers often reject invalid input early.
if !strings.Contains(email, "@") {
return errors.New("invalid email address")
}
Filtering collections
Used when iterating through slices of strings.
for _, name := range names {
if strings.Contains(name, "test") {
fmt.Println(name)
}
}
Case-normalized checks
Many codebases normalize strings before searching.
if strings.Contains(strings.ToLower(role), "admin") {
fmt.Println("admin-related role")
}
Configuration and environment checks
Developers inspect environment values or config strings.
if strings.Contains(host, "localhost") {
fmt.Println("running locally")
}
Error handling and diagnostics
Substring checks are sometimes used to classify text-based errors.
if err != nil && strings.Contains(err.Error(), "timeout") {
fmt.Println("request timed out")
}
This pattern exists, though structured error handling is usually better when available.
Combined with other string helpers
It is common to use Contains together with:
strings.HasPrefixstrings.HasSuffixstrings.TrimSpacestrings.ToLowerstrings.Split
These helpers often appear together in parsing and validation code.
Common Mistakes
1. Forgetting to import the strings package
Broken code:
package main
import "fmt"
func main() {
fmt.Println(strings.Contains("hello", "he"))
}
Problem:
stringsis not imported, so the code will not compile.
Fix:
import (
"fmt"
"strings"
)
2. Trying to call .contains() like other languages
Broken code:
someString.contains("something")
Problem:
- Go strings do not have a
containsmethod.
Fix:
strings.Contains(someString, "something")
3. Expecting case-insensitive behavior
Broken assumption:
strings.Contains("Hello", "hello") // false
Problem:
Containsis case-sensitive.
Fix:
strings.Contains(strings.ToLower("Hello"), strings.ToLower("hello")) // true
4. Using Contains when prefix or suffix checks are better
Sometimes you do not want to know whether text appears anywhere. You want to know whether it starts or ends with something.
Less precise:
strings.Contains(fileName, ".go")
Better if checking file extension:
strings.HasSuffix(fileName, ".go")
5. Confusing empty substring behavior
strings.Contains("hello", "") // true
This surprises some beginners. An empty string is considered to be contained in every string.
6. Searching formatted data too loosely
strings.Contains("id=12", "2") // true
This may be technically correct, but too broad for structured parsing. If the input has structure, parsing may be safer than substring matching.
Comparisons
| Concept | What it checks | Example | Best use |
|---|---|---|---|
strings.Contains(s, sub) | Whether sub appears anywhere in s | strings.Contains("golang", "la") | General substring search |
strings.HasPrefix(s, prefix) | Whether s starts with prefix | strings.HasPrefix("/api/users", "/api") | Route and path checks |
strings.HasSuffix(s, suffix) | Whether s ends with suffix | strings.HasSuffix("main.go", ".go") | File extension checks |
strings.Index(s, sub) | Position of sub in s, or -1 if missing | strings.Index("golang", "la") | When you need the location |
Contains vs Index
Use Contains when you only care about true or false.
strings.Contains("golang", "go") // true
Use Index when you also need the position.
strings.Index("golang", "go") // 0
Contains vs regular expressions
Containsis simpler and clearer for plain text matching.- Regular expressions are better for patterns.
Example:
strings.Contains("user123", "123")
Use this for direct text checks.
If you need something like "contains one or more digits at the end," a regex may be more appropriate.
Cheat Sheet
import "strings"
Check whether a string contains a substring
strings.Contains(s, sub)
- Returns
trueorfalse - Case-sensitive
- Works on plain strings
Examples
strings.Contains("hello world", "world") // true
strings.Contains("hello world", "Go") // false
strings.Contains("GoLang", "go") // false
Case-insensitive version
strings.Contains(strings.ToLower(s), strings.ToLower(sub))
Related helpers
strings.HasPrefix(s, prefix)
strings.HasSuffix(s, suffix)
strings.Index(s, sub)
Important edge case
strings.Contains("abc", "") // true
Common pattern
if strings.Contains(text, "error") {
fmt.Println("found error text")
}
FAQ
How do I check if a string contains text in Go?
Use strings.Contains(mainString, subString) from the strings package.
Is strings.Contains case-sensitive in Go?
Yes. strings.Contains("Go", "go") returns false.
What package do I need for substring checks in Go?
You need the standard library package strings.
import "strings"
Can I use .contains() directly on a string in Go?
No. Go strings do not have a .contains() method. Use strings.Contains(...) instead.
How do I do a case-insensitive contains check in Go?
A common approach is to convert both values to the same case first:
strings.Contains(strings.ToLower(a), strings.ToLower(b))
What happens if the substring is empty?
strings.Contains(s, "") returns true.
Should I use Contains or HasSuffix for file extensions?
Use strings.HasSuffix when checking whether a filename ends with an extension like .go or .json. It is more precise than Contains.
Mini Project
Description
Build a small Go program that filters a list of log messages and prints only the ones containing the word error. This demonstrates how substring checks are used in scripts, debugging tools, and backend utilities.
Goal
Create a Go program that scans several strings and prints the messages that contain a target substring.
Requirements
- Import and use the
stringspackage. - Store several log messages in a slice.
- Check each log message for a target substring.
- Print only the matching messages.
- Make the match case-insensitive.
Keep learning
Related questions
Are Go Maps Passed by Value or Reference?
Learn Go map parameter and return semantics: maps are passed by value, while copies share underlying data. Know when map pointers are useful.
Authentication for Go REST APIs: Sessions, Tokens, and Middleware
Learn practical authentication patterns for Go REST APIs, including password hashing, server sessions, bearer tokens, middleware, and security rules.
Automatic Build Versioning in Go: Embed Incrementing Build Numbers
Learn how to add automatic build versioning in Go using linker flags, build metadata, CI counters, and Git-based version values.