Compare Strings in Golang: 7 Methods and When to Use Them
Justas Vitaitis
Last updated -
In This Article
This is a guide on how to compare strings in Golang . You will learn which method you should use for the best performance in each use case. In addition, we will explore how you can combine different methods to achieve the best possible performance, no matter what kind of Golang string comparison you are doing.
If you know how to compare strings, this might seem like a trivial question. You can just pick a method that works and go with it. However, there are huge performance issues in some Golang functions for string comparison, and they are there by design.
Therefore, you need to know these caveats to ensure that your code is as fast as it can be.
Let’s explore these methods, see some examples, and you can even test your code live using the links we will provide.
The Best Method to Compare Strings in Golang
There are two clear winners for string comparisons in Golang, and there is a clear loser. Then there are other methods used for different needs. We will discuss in detail the best way to use each of them, but here is a quick summary of all methods we are going to explore today:
- Equality operators (==, !=): The best option for case-sensitive string comparison.
- strings.EqualFold(): The best method for case-insensitive string comparison.
- strings.Compare(): The worst method for case-sensitive or case-insensitive comparisons.
- len(): This function allows you to compare the size of two strings. It is useful in itself, but also as a performance-enhancing tool for the other functions.
- strings.Contains(): The best method to compare case-sensitive substrings.
- strings.Contains() + strings.ToLower(): The best method to compare case-insensitive substrings.
- Inequality operators ( >, <, >=, <= ): The best method to compare strings based on their alphabetical order.
Let’s dive into the details now.
len()
Let’s start with a simple yet often forgotten function. len() allows you to compare strings in Golang by their size in bytes. Therefore, if you want to know if a string is bigger than another one, this method is the way to go.
Here is a simple way to use it:
package main
import "fmt"
func main() {
var stringA = "John"
var stringB = "Paul"
if len(stringA) == len(stringB) {
fmt.Println("The size is the same")
} else {
fmt.Println("The size is different")
}
// Result: The size is the same
stringA = "Ringo"
stringB = "George"
if len(stringA) == len(stringB) {
fmt.Println("The size is the same")
}
if len(stringA) < len(stringB) {
fmt.Println("A is smaller than B")
} else {
fmt.Println("A is bigger than B")
}
// Result: A is smaller than B
}
The len() function is quite useful for improving the other functions as well. When you run a string comparison function such as “==”, Go compares characters one by one. This takes quite some time.
But checking the string’s size is really fast with len(). Therefore, you can add a test to see if the string sizes are the same before running other equality tests. This allows you to reduce processing times whenever the strings are different.
Let’s see how it works in real examples with each of the functions.
Equality Operators (==, !=)
The equality operators allow you to check if a string is equal to or different from the other. It checks for an exact match, so it is case-sensitive. It is the fastest option for case-sensitive comparisons, and it is the recommended option by the Golang team.
You can combine the equality operators with the len() function for even better performance. In this case, you check if the strings are the same size first, and then you run the equality operators on the string’s contents.
If you want to use the equality operators in case-insensitive comparisons, you can use the strings.ToLower() function to convert all characters to lowercase and then check if two strings are equal. You don’t need to do it, though. The EqualFold() function is a better option for case-insensitive comparisons.
Here are some examples of how you can use the equality operators to compare strings in Golang:
package main
import (
"fmt"
"strings"
)
func main() {
var stringA = "John"
var stringB = "Paul"
if stringA == stringB {
fmt.Println("John is Paul")
} else {
fmt.Println("John isn't Paul")
}
// Result: John isn't Paul
stringA = "John"
stringB = "john"
if stringA == stringB {
fmt.Println("John is john")
} else {
fmt.Println("John isn't john")
}
// Result: John isn't john
stringA = "John"
stringB = "john"
if strings.ToLower(stringA) == strings.ToLower(stringB) {
fmt.Println("John is john when converted to lowercase")
} else {
fmt.Println("John isn't john when converted to lowercase")
}
// Result: John is john when converted to lowercase
}
stringA = "John"
stringB = "John Lennon"
if len(stringA) == len(stringB) {
if stringA == stringB {
fmt.Println("The sizes are the same, but John isn't John Lennon")
} else {
fmt.Println("The sizes are the same, and John is John Lennon")
}
} else {
fmt.Println("The sizes are different")
}
// Result: The sizes are different
The Inequality Operators ( >, <, >=, <=)
When comparing numbers, it’s quite simple to understand what these operators mean. But when it comes to strings, they behave in a special way.
If you use the inequality operators to compare strings, you are comparing the dictionary order of these strings. You’ll often see the technical docs refer to it as lexicographic order . That’s the same thing as dictionary order, which can be tricky when comparing strings with numbers and letters.
Notice that lower order means that a number comes first in the dictionary. So “abc” has a lower order than “def”. Also, upper case letters come before lowercase letters. So “ABC” has a lower order than “abc”, which means that “ABC” comes first in the dictionary.
Check out how it works:
// IPRoyal Golang string compare examples
package main
import (
"fmt"
)
func main() {
var stringA = "John"
var stringB = "john"
if stringA < stringB {
fmt.Println("John comes before john")
} else {
fmt.Println("John doesn't come before john")
}
// Result: John comes before john - uppercase letters come first
stringA = "Johnny"
stringB = "John Lennon"
if stringA < stringB {
fmt.Println("Johnny comes before John Lennon")
} else {
fmt.Println("Johnny doesn't come before John Lennon")
}
// Result: Johnny doesn't come before John Lennon - smaller words come first
stringA = "10 John"
stringB = "2 John"
if stringA < stringB {
fmt.Println("10 John comes before 2 John")
} else {
fmt.Println("10 John doesn't come before 2 John")
}
// Result: 10 John comes before 2 John - Even though 10 is bigger than 2, it is a dictionary comparison so 1 comes before 2
}
strings.Compare()
Let’s be clear, even the Golang team says that this function shouldn’t be used at all. Here is what they have in the comparison declaration:
func Compare(a, b string) int {
// NOTE(rsc): This function does NOT call the runtime cmpstring function,
// because we do not want to provide any performance justification for
// using strings.Compare. Basically no one should use strings.Compare.
// As the comment above says, it is here only for symmetry with package bytes.
// If performance is important, the compiler should be changed to recognize
// the pattern so that all code doing three-way comparisons, not just code
// using strings.Compare, can benefit.
[...]
}
So no one should use Compare(). Their words, not mine!
Anyway, if you do want to use it, or if you want to see how it works to refactor some old code, the general idea is that this function performs case-sensitive comparison. But instead of returning a true/false result, it returns zero if they are equal or the lexicographically (dictionary) comparison of the two strings.
Therefore, it is similar to running the equality operator (with “different than”), and if strings are different, running the inequality operator. Here are the possible return values for strings.Compare( stringA, stringB ):
- if stringA == stringB, return 0
- if stringA > stringB, return 1 - meaning that A is after B in the dictionary
- if stringA < stringB, return -1 - meaning that A is before B in the dictionary
You can see it in action here:
package main
import (
"fmt"
"strings"
)
func main() {
var stringA = "John"
var stringB = "John"
fmt.Println(strings.Compare(stringA, stringB))
// Result: 0 - both are equal
stringA = "John"
stringB = "john"
fmt.Println(strings.Compare(stringA, stringB))
// Result: -1 - John comes first in the dictionary
stringA = "Johnny"
stringB = "John Lennon"
fmt.Println(strings.Compare(stringA, stringB))
// Result: 1 - John Lennon comes first in the dictionary
stringA = "10 John"
stringB = "2 John"
fmt.Println(strings.Compare(stringA, stringB))
// Result: -1 - 10 John comes first in the dictionary
}
strings.Contains()
You can check if one string is present in its entirety inside another string with the contains function. This is a case-sensitive comparison.
It returns true if the string contains the other and false if not. To remember the order of the arguments, notice that you can translate the code “Contains( a, b )” as “does ‘a’ contains ‘b` ?”, thus A is the bigger string, and B is the substring you are testing.
Here is how it works:
package main
import (
"fmt"
"strings"
)
func main() {
var stringA = "The Beatles were an amazing band"
var stringB = "John"
fmt.Println(strings.Contains(stringA, stringB))
// Result: false
stringA = "The Beatles were: John, Paul, George, Ringo"
stringB = "John"
fmt.Println(strings.Contains(stringA, stringB))
// Result: true
stringA = "The Beatles were: John, Paul, George, Ringo"
stringB = "john"
fmt.Println(strings.Contains(stringA, stringB))
// Result: false
}
strings.Contains() + strings.ToLower()
Out of the box, the contains function is case-sensitive. If you need to compare if a string contains another substring ignoring their case, you can convert both to lowercase prior to your comparison.
Check out some examples:
// IPRoyal Golang string compare examples
package main
import (
"fmt"
"strings"
)
func main() {
var stringA = "The Beatles were an amazing band"
var stringB = "John"
fmt.Println(strings.Contains(strings.ToLower(stringA), strings.ToLower(stringB)))
// Result: false
stringA = "The Beatles were: John, Paul, George, Ringo"
stringB = "John"
fmt.Println(strings.Contains(strings.ToLower(stringA), strings.ToLower(stringB)))
// Result: true
stringA = "The Beatles were: John, Paul, George, Ringo"
stringB = "john"
fmt.Println(strings.Contains(strings.ToLower(stringA), strings.ToLower(stringB)))
// Result: true
}
Conclusion
Today you’ve learned the best methods to compare strings in Golang. In addition, you learned how you can combine the best-performing methods with other Golang functions to achieve the best performance possible.
By the end of the day, you should be able to compare strings by their contents, size, dictionary order and substrings.
We hope you’ve enjoyed it. If you haven’t already, make sure to check our guide on how to build a Golang web scraper . See you again next time!
FAQ
Can you use == for strings in Golang?
Yes, you can use the equality comparison for strings in Golang. It looks for an exact match, so it is a case-sensitive search.
If you require a case-insensitive method, consider using strings.EqualFold() since it is more performant for that task. Alternatively, you could use the strings.ToLower() method, but it won’t be as fast.
You shouldn’t use the strings.Compare() function, as it isn’t recommended by the Golang team and it is significantly slower than its alternatives.
How do you find the length of a string in Golang?
You can use len() to find the byte size of a string. This can lead to unpredicted results if you are using some characters that occupy more than one byte. If you want to know the number of characters in a string, you can use len([]rune(string), such as len([]rune(“abc”).
How do I convert an int to a string in Golang?
You can use the strconv function. In it, you can use the Itoa method for a direct conversion of base 10 integers, such as strconv.Itoa(number), or you can use the FormatInt method to convert from different bases, such as strconv.FormatInt(number, 10).
Author
Justas Vitaitis
Senior Software Engineer
Justas is a Senior Software Engineer with over a decade of proven expertise. He currently holds a crucial role in IPRoyal’s development team, regularly demonstrating his profound expertise in the Go programming language, contributing significantly to the company’s technological evolution. Justas is pivotal in maintaining our proxy network, serving as the authority on all aspects of proxies. Beyond coding, Justas is a passionate travel enthusiast and automotive aficionado, seamlessly blending his tech finesse with a passion for exploration.
Learn More About Justas Vitaitis