Skip to content
Lesson 4 of 14

Step 1 of 5 · Reading · ~4 min

Learn

Strings

String Basics

A Go string is an immutable sequence of bytes holding UTF-8 text. Those two words explain every string behaviour that surprises newcomers. By the end of this lesson you can measure a string, clean up text that arrived from outside your program, and produce a changed copy of it.

Immutable: you never edit, you always build

go

Nothing edits a string in place. Every function in the strings package leaves its argument alone and hands you a brand-new string as its return value. Throw that return value away and nothing has happened:

go

The cure is always the same: keep the result. Store it in a variable, or pass it straight to whatever needs it.

Bytes, not characters

len(s) counts bytes, and s[i] is one byte - a number, not a character. In pure ASCII a byte and a character are the same thing, which hides the difference until the first accented letter arrives:

go

Working rule: len and indexing for ASCII and binary formats, []rune(s) when you need to count human characters ([]rune(s) turns the string into a list of its characters; lists get their own lesson, Slices, later). A later lesson introduces the loop that walks a string rune by rune.

The toolbox

Nearly every string job is one call. Each of these returns a value and none of them touches its argument:

go

TrimSpace is the one you reach for on input. Text that arrives from outside your program almost always carries an invisible line ending, and often padding a human typed by accident. "hi\n", " hi" and "hi" are three different strings, so comparisons fail for reasons you cannot see on screen.

A worked example

Sloppily typed filename; is it a Go file?

go

The tidy text lives in clean; raw keeps its padding forever. And a strings call is an ordinary expression: park its result in a variable, or hand it straight to the next function.

Gluing pieces together

+ concatenates: label := "user:" + id, which is perfect for a handful of pieces. Because strings are immutable, each + copies both sides into a fresh allocation, so gluing thousands of fragments one at a time is slow; strings.Builder exists for that, once you have loops.

Common mistakes

  • Calling the function and then printing the original. strings.ToUpper(t) does not change t. If you print t afterwards, the input go is fun comes back out as go is fun.
  • Trimming only the line ending. strings.TrimRight(t, "\r\n") removes the newline but leaves a human's padding, and strings.Trim(t, " ") misses tabs. Padded input then prints as GO IS FUN , which fails a character-exact comparison. TrimSpace handles spaces, tabs and line endings at both ends in one call.
  • Grabbing the neighbouring function. ToLower where you meant ToUpper prints go is fun; nothing warns you, because both calls are legal.
  • Trying to edit in place. t[0] = 'G' does not compile. Build a new string instead.

Your exercise

Print the line the starter has read for you as uppercase text with no whitespace around it. The starter reads the line, strips the line ending and then prints the line unchanged, which is wrong for every test; that print is the statement you replace. The likeliest slip is forgetting that a strings call hands the new text back to you rather than changing the variable you passed in.

Up nextFormatted PrintingStrings

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…