The len function
The built-in len function returns the length of a string. You don't import anything and you don't call it as a method; you pass the string as an argument.
message := "I love pancakes"
fmt.Println(len(message)) // 15
The result is an int. In "I love pancakes", count the letters and the two spaces and you get 15.
One detail matters for text beyond English: len counts bytes, not characters. For ASCII text the two are the same. For "héllo", len returns 6, because é uses two bytes in UTF-8. To count characters, use utf8.RuneCountInString(s) from the unicode/utf8 package, which returns 5 for that word.
Using len to reach the end
Indexes start at 0, so a string of length n has valid indexes 0 to n - 1. The last character is at len(s) - 1. Go has no negative indexes, so this expression is how you reach the end without counting by hand.
The same idea works for slicing. The last 5 characters start at index len(s) - 5 and run to the end, so the slice is s[len(s)-5:].
Exercise step by step
The lesson starts with message := "I love pancakes".
- Print the length. Pass
len(message)tofmt.Println. It prints 15. - Print the last character. The last index is
len(message) - 1, which is 14. Indexing gives a byte, so wrap it instring(...)to print the letter instead of its number. - Print the last five characters. Start the slice at
len(message)-5, which is 10, and leave out the end bound so it runs to the end.
The solution in Go
message := "I love pancakes"
fmt.Println(len(message))
fmt.Println(string(message[len(message) - 1]))
fmt.Println(message[len(message)-5:])
The output is:
15
s
cakes
Spacing around the minus sign makes no difference to the compiler: len(message) - 1 and len(message)-1 mean the same thing.
Details worth knowing
- The empty string.
len("")is 0. Thens[len(s)-1]iss[-1], which panics at run time withindex out of range [-1]. Check the length before taking the last character of a string that might be empty. - Slices near the limit.
s[len(s)-5:]panics if the string is shorter than 5 bytes, because the start would be negative. Guard it with anif len(s) >= 5check when the length isn't known. lenis cheap. A string stores its length, solen(s)takes constant time and doesn't scan the text.- Other types.
lenis not only for strings. It also works on slices, arrays, maps and channels, with the same spelling.
Both examples depend on the length being at least what the expression subtracts, which is why the empty-string case above matters.
Common mistakes
- Using
len(message)as an index. It is one past the last valid position. The last character is atlen(message) - 1. - Forgetting
string(...).message[len(message)-1]alone prints 115, the number fors. - Calling it like a method.
message.len()andmessage.lengthdon't exist in Go. Writelen(message). - Counting the wrong thing. Spaces count as characters, so
"I love pancakes"is 15 and not 13.
A worked example
Take the text "Go!". Its length is 3, so the valid indexes are 0, 1 and 2, and the last one is len("Go!") - 1, which is 2. The byte at index 2 is !. For the last two characters, the slice starts at 3 - 2 = 1, so s[len(s)-2:] is o!. Working a small string out by hand like this is a good way to check an index expression before you rely on it.
The length also drives loops. A loop such as for i := 0; i < len(s); i++ visits every index exactly once, and the condition uses <, not <=, for the same reason the last index is len(s) - 1.
Key takeaways
len(s)returns the number of bytes in the string.- The last index is
len(s) - 1, and the lastkbytes ares[len(s)-k:]. - Going past either end of a string makes the program panic, so check the length when it can be small.