Question
Is there a Go function equivalent to Java's startsWith() that checks whether one string begins with another string?
For example, how can I check whether str2 starts with str1 (that is, whether str1 is a prefix of str2)?
Short Answer
Go provides strings.HasPrefix in the standard library. It checks whether a string starts with a specified prefix and returns a bool: true when the prefix matches, otherwise false. You will learn its argument order, behavior, and practical uses.
Concept
Use strings.HasPrefix from Go's built-in strings package to test a string prefix.
strings.HasPrefix(s, prefix)
sis the complete string to inspect.prefixis the text that must appear at the beginning ofs.- The result is a boolean:
trueorfalse.
strings.HasPrefix("golang", "go") // true
strings.HasPrefix("golang", "lang") // false
This matters whenever a program needs to classify, validate, or route text based on how it begins. For example, an HTTP service may recognize API paths beginning with /api/, or a file-processing tool may select files whose names begin with report-.
HasPrefix is part of the Go standard library, so no third-party package is required.
Mental Model
Think of a prefix as the opening label on a package.
If a package label reads ORDER-1042, you can check whether it starts with ORDER-. You do not need to inspect the entire label; you only compare the characters at the front.
In strings.HasPrefix(s, prefix), the first argument is the whole package label, and the second argument is the opening label you expect.
Syntax and Examples
Import the strings package, then call strings.HasPrefix.
package main
import (
"fmt"
"strings"
)
func main() {
filename := "report-2025.csv"
if strings.HasPrefix(filename, "report-") {
fmt.Println("This is a report file.")
}
}
Output:
This is a report file.
The call checks whether filename begins with "report-".
Store the result
isSecureURL := strings.HasPrefix("https://example.com", "https://")
fmt.Println(isSecureURL) // true
Important argument order
The complete string comes first:
strings.HasPrefix("hello world", "hello") // true
This is similar to Java's receiver-based syntax:
"hello world".startsWith("hello")
In Go, the receiver becomes the first function argument.
Step by Step Execution
Consider this program:
package main
import (
"fmt"
"strings"
)
func main() {
path := "/api/users"
isAPIPath := strings.HasPrefix(path, "/api/")
fmt.Println(isAPIPath)
}
Step by step:
pathstores"/api/users".strings.HasPrefixcompares the beginning ofpathwith"/api/".- The first five characters match:
/api/. - The function returns
true. isAPIPathreceivestrue.fmt.Printlnprintstrue.
If path were "/health", the comparison would fail and the result would be false.
Real World Use Cases
strings.HasPrefix is useful wherever the beginning of text has meaning.
- HTTP routing: Identify requests such as
/api/usersor/admin/settings. - Configuration: Read environment variable names with a shared prefix, such as
APP_. - File processing: Select generated files named
backup-...orreport-.... - Protocol handling: Recognize URL schemes such as
https://,mailto:, orgit@. - Log processing: Filter lines beginning with
ERROR:orWARN:. - Command-line tools: Identify flags beginning with
--, such as--verbose.
Real Codebase Usage
In real Go projects, prefix checks are commonly combined with validation and early returns.
Guard clause for validation
func validateAPIPath(path string) error {
if !strings.HasPrefix(path, "/api/") {
return fmt.Errorf("path must start with /api/")
}
return nil
}
The early return keeps invalid input from reaching later logic.
Classify values while processing data
func internalEmails(emails []string) []string {
result := make([]string, 0)
for _, email := range emails {
if strings.HasPrefix(email, "admin@") {
result = append(result, email)
}
}
return result
}
Normalize before comparing when needed
Prefix checks are case-sensitive. If input may have inconsistent casing, normalize it deliberately:
scheme := "HTTPS://example.com"
isHTTPS := strings.HasPrefix(strings.ToLower(scheme), "https://")
fmt.Println(isHTTPS) // true
Only normalize when case should not matter for your application. Some identifiers and paths are intentionally case-sensitive.
Common Mistakes
Reversing the arguments
The full string must be first and the expected prefix second.
// Incorrect: asks whether "go" starts with "golang".
strings.HasPrefix("go", "golang") // false
// Correct
strings.HasPrefix("golang", "go") // true
Forgetting to import strings
// This will not compile unless the strings package is imported.
strings.HasPrefix("golang", "go")
Add:
import "strings"
Expecting case-insensitive matching
strings.HasPrefix("GoLang", "go") // false
HasPrefix compares case exactly. Use strings.ToLower first only if a case-insensitive rule is appropriate.
Using Contains when position matters
strings.Contains("my-api-path", "api") // true
strings.HasPrefix("my-api-path", "api") // false
Contains checks anywhere in the string. HasPrefix checks only the beginning.
Forgetting that an empty prefix matches
strings.HasPrefix("hello", "") // true
Every string starts with an empty string. Validate the prefix separately if empty prefixes are not allowed.
Comparisons
| Task | Go function | Example | Result |
|---|---|---|---|
| Check the beginning of a string | strings.HasPrefix | strings.HasPrefix("golang", "go") | true |
| Check the end of a string | strings.HasSuffix | strings.HasSuffix("main.go", ".go") | true |
| Check anywhere in a string | strings.Contains | strings.Contains("golang", "lan") | true |
| Find the first position of text | strings.Index | strings.Index("golang", "lan") | 2 |
HasPrefix versus manual slicing
You could compare a slice manually:
word := "golang"
if len(word) >= 2 && word[:2] == "go" {
fmt.Println("match")
}
But strings.HasPrefix(word, "go") is clearer and avoids writing length checks. Manual slicing without a length check can panic when the string is shorter than the prefix.
HasPrefix versus regular expressions
Use HasPrefix for a fixed, literal prefix. It is simpler than a regular expression such as ^api-. Use a regular expression only when the prefix itself has a pattern, such as specific digit or letter rules.
Cheat Sheet
import "strings"
matched := strings.HasPrefix(s, prefix)
| Rule | Detail |
|---|---|
| Argument order | Full string first, prefix second: HasPrefix(s, prefix) |
| Return type | bool |
| Case sensitivity | Case-sensitive |
| Empty prefix | Always returns true |
| Prefix longer than string | Returns false |
| Standard library | Import strings |
Examples:
strings.HasPrefix("main.go", "main") // true
strings.HasPrefix("main.go", ".go") // false
strings.HasPrefix("main.go", "") // true
strings.HasPrefix("go", "golang") // false
strings.HasPrefix("Go", "go") // false
Related helpers:
strings.HasSuffix("main.go", ".go")
strings.Contains("main.go", "ain")
FAQ
Is there a startsWith function in Go?
Go uses strings.HasPrefix(s, prefix) instead of a method named startsWith.
What is the equivalent of Java String.startsWith() in Go?
Use strings.HasPrefix. Java's text.startsWith(prefix) is equivalent to Go's strings.HasPrefix(text, prefix).
Does strings.HasPrefix ignore uppercase and lowercase letters?
No. It is case-sensitive. For case-insensitive comparisons, normalize both values with strings.ToLower when that matches your requirements.
Does strings.HasPrefix work with UTF-8 strings?
Yes. It compares string bytes and safely determines whether the exact prefix byte sequence is present. A normal UTF-8 prefix works as expected.
What happens if the prefix is empty?
It returns true, because every string starts with an empty string.
Can I use HasPrefix with a []byte?
Not directly. For byte slices, use bytes.HasPrefix from the bytes package.
Is HasPrefix safe when the prefix is longer than the string?
Yes. It returns false; it does not panic.
Mini Project
Description
Build a small URL classifier that accepts a list of URLs and labels each one as secure (https://), insecure (http://), or unsupported. This demonstrates how prefix checks can route input into different program behavior.
Goal
Classify each URL by its scheme using strings.HasPrefix.
Requirements
Requirement 1
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.