Golang Compare Strings: Equality, Ordering, and Case-Insensitive Match

Compare strings in Go with == and !=, lexicographic order with < and >, strings.EqualFold for case-insensitive match, strings.Compare for three-way results, and trimming input before comparing.

Published

Updated

Read time 5 min read

Reviewed byDeepak Prasad

Golang Compare Strings: Equality, Ordering, and Case-Insensitive Match

This page is for Go beginners who need golang compare strings for equality, ordering, or case-insensitive checks. Go stores strings as read-only byte sequences; == compares those bytes exactly. For “does this string contain…”, see string contains; for general functions, see functions in Go.

Tested with Go 1.24 on Linux.


Quick answer: how to compare strings in Go

Use == for exact equality and != for inequality. Use <, >, <=, >= for lexicographic (byte-wise) ordering. Use strings.EqualFold for case-insensitive equality under Unicode simple case-folding. Use strings.Compare only when you want a single three-way int result; for most code the operators read more clearly.


Compare strings for equality

== compares every byte in both strings. Case and spacing matter: "Go" and "go" are not equal.

go
package main

import "fmt"

func main() {
	a, b, c := "GoLinux", "GoLinux", "golinux"
	fmt.Println(a == b, a == c, a != c)
}
Output

You should see true false true.


Lexicographic ordering with operators

String ordering uses byte-wise lexicographic order of the UTF-8 encoding, which matches dictionary order for ASCII letters.

go
package main

import "fmt"

func main() {
	fmt.Println("apple" < "banana", "Z" < "a", "01" < "1")
}
Output

You should see three true values: apple is before banana, uppercase ASCII letters sort before lowercase, and "01" is less than "1" because the first byte '0' is less than '1'.


strings.Compare (three-way)

strings.Compare(a, b) returns 0 if a == b, -1 if a < b, and +1 if a > b. It is equivalent to the operator chain but easy to misuse when you only need a boolean—prefer == or < for clarity.

go
package main

import (
	"fmt"
	"strings"
)

func main() {
	fmt.Println(strings.Compare("a", "b"))  // -1 : a < b
	fmt.Println(strings.Compare("b", "a"))  // +1 : b > a
	fmt.Println(strings.Compare("x", "x")) // 0  : equal
}
Output

You should see -1, 1, and 0 on one line each.


Case-insensitive comparison: strings.EqualFold

strings.EqualFold reports whether two strings are equal under Unicode simple case-folding. Prefer it over strings.ToLower(a) == strings.ToLower(b) to avoid allocating two new strings and to get defined Unicode semantics.

go
package main

import (
	"fmt"
	"strings"
)

func main() {
	fmt.Println(strings.EqualFold("GoLinux", "GOLINUX"))
	fmt.Println(strings.EqualFold("GoLinux", "GoLiNux"))
	fmt.Println("GoLinux" == "GOLINUX")
}
Output

You should see true, true, then false for the exact == line.


Length: bytes vs runes

len(s) returns the number of bytes in a string, not necessarily the number of Unicode code points (runes) people think of as “characters.” For ASCII-only text, byte length and rune count usually match; for UTF-8 beyond ASCII, they often do not.

go
package main

import (
	"fmt"
	"unicode/utf8"
)

func main() {
	ascii := "hello"
	hindi := "नमस्ते"
	emoji := "😊"

	fmt.Println("ascii", len(ascii), "bytes,", utf8.RuneCountInString(ascii), "runes")
	fmt.Println("hindi", len(hindi), "bytes,", utf8.RuneCountInString(hindi), "runes")
	fmt.Println("emoji", len(emoji), "bytes,", utf8.RuneCountInString(emoji), "runes")
}
Output

You should see hello as 5 and 5, Hindi with more bytes than runes, and the smiley as 4 bytes but 1 rune.

Use len(s) when you care about storage size, buffer limits, or wire-format length. Use utf8.RuneCountInString or for _, r := range s when you care about code-point count. Visually “one character” can still span multiple code points (combining marks), so rune count is not always the same as glyph count.

Goal Better choice
Compare byte size len(s)
Check storage or payload size len(s)
Count UTF-8 code points (runes) utf8.RuneCountInString(s)
Visit each code point for _, r := range s
Validate user-facing length Prefer rune rules you define; do not assume len is “letters”

Length checks are byte-based unless you count runes explicitly (with import "unicode/utf8" in real code):

go
if len(s) > 10 {
	// more than 10 bytes, not necessarily more than 10 runes
}
if utf8.RuneCountInString(s) > 10 {
	// more than 10 UTF-8 code points
}

Short rule:

text
Use len(s) for bytes.
Use rune counting when limits are defined in code points, not bytes.

Whitespace and newlines

User input, files, and environment variables often end with spaces or \n. Compare after strings.TrimSpace (or a more specific trim) when those differences should not matter.

go
package main

import (
	"fmt"
	"strings"
)

func main() {
	fileLine := "yes\n"
	answer := "yes"
	fmt.Println(fileLine == answer)
	fmt.Println(strings.TrimSpace(fileLine) == answer)
}
Output

You should see false then true.


Mistakes to avoid

Using strings.Compare only to get ==—write a == b instead.

Forgetting that == is case-sensitive—use EqualFold when case should be ignored.

Comparing raw stdin or file lines without trimming when trailing newlines break equality.

Using len as a proxy for “number of letters” in non-ASCII text—len counts bytes.

Lowercasing both sides for case-insensitive checks—prefer EqualFold for semantics and allocations.


Go string comparison cheat sheet

Goal Approach
Exact equality a == b
Not equal a != b
Lexicographic order <, >, <=, >=
Three-way int strings.Compare
Case-insensitive strings.EqualFold
Messy user/file input strings.TrimSpace (or targeted trim)
Byte length len(s)
Rune count utf8.RuneCountInString or range

Summary

Golang compare strings with == and != for exact equality, operators for byte-wise ordering, and strings.EqualFold for case-insensitive UTF-8 folding. Reserve strings.Compare for APIs that want -1/0/+1. Remember default comparisons are case-sensitive, raw input may need trimming, and len counts bytes. For deeper UTF-8 background, see Go blog: strings.


References


Frequently Asked Questions

1. How do I compare two strings for equality in Go?

Use == for exact byte-wise equality and != for inequality; comparisons are case-sensitive unless you use strings.EqualFold.

2. How do I compare strings alphabetically in Go?

Use <, >, <=, >= for lexicographic order on the underlying bytes, or strings.Compare for a three-way int result.

3. How do I do case-insensitive string comparison in Go?

Use strings.EqualFold(s, t); it applies Unicode simple case-folding without forcing you to allocate lowercased copies like strings.ToLower(s) == strings.ToLower(t).

4. What does strings.Compare return?

0 if a == b, -1 if a < b, and +1 if a > b in lexicographic byte order; for most code the operators are clearer.

5. Does len(s) count characters for string comparison?

len counts bytes in the string; for Unicode code points use utf8.RuneCountInString or range over the string.
Tuan Nguyen

Data Scientist

Proficient in Golang, Python, Java, MongoDB, Selenium, Spring Boot, Kubernetes, Scrapy, API development, Docker, Data Scraping, PrimeFaces, Linux, Data Structures, and Data Mining. With expertise …