When a string's length is constant

February 27, 2023

String Types

The length of a string s can be discovered using the built-in function len. The length is a compile-time constant if the string is a constant. A string’s bytes can be accessed by integer indices 0 through len(s)-1. It is illegal to take the address of such an element; if s[i] is the i‘th byte of a string, &s[i] is invalid.

There are a couple of nuggets in this paragraph.

First, you may recall from our introduction to constants that a constant may represent “… the result value of some built-in functions such as … len applied to some expressions.

Now we have an example of such an expression: Calling len on a string constant returns a constant value. So this is valid:

const str = "Hello, World"
const strLen = len(str) // 12

However, this is not:

var str = "Hello, " + name
const strLen = len(str) // Invalid (unless `name` itself is a string constant as well)

Second, the final sentence is interesting for reasons that aren’t immediately obvious.

First note that taking the address of a slice is perfectly valid:

	var s = []byte("Hello, World")
	var x = &s[3]

	fmt.Println(x) // 0xc00001c033 or some other memory location

Now that I have a pointer to a specific byte in my slice, I can do things with it, including modifying it:

	var s = []byte("Hello, World")
	var x = &s[3]
	*x = 'X'

	fmt.Println(string(s)) // HelXo, World

But if we could do the same thing with a string, we would violate the immutability trait of strings.

This is why it is impossible to take the address of an element of a string.

Quotes from The Go Programming Language Specification, Version of January 19, 2023


Share this

Direct to your inbox, daily. I respect your privacy .

Unsure? Browse the archive .

Related Content


Constant lengths and expressions

A few of the built-in functions are very special, in that they can evaluate to constant expressions. len and cap are two such functions. But they aren’t always evaluated to constant expressions, sometimes they’re more normal-ish runtime functions. Length and capacity … The expression len(s) is constant if s is a string constant. The expressions len(s) and cap(s) are constants if the type of s is an array or pointer to an array and the expression s does not contain channel receives or (non-constant) function calls; in this case s is not evaluated.


Evaluation of range expressions

For statements with range clause … The range expression x is evaluated once before beginning the loop, with one exception: if at most one iteration variable is present and len(x) is constant, the range expression is not evaluated. The first part of this seems pretty self-evident, as it follows the same pattern as a for statement with a for clause: The expression needs to be evaluated once before the loop executes.


Constant errors

Last week I talked about how to create your own errors. Expanding on that idea, here’s a trick I like to use: Constant errors! Constants in Go are limited to simple underlying types: bool, string, and the numeric types. If we create our own type, which both satisfies the error interface, and has such an underlying type, we can then create constant error values: type errString string func (e errString) Error() string { return string(e) } const ErrTooManyFrogs = errString("too many frogs") Okay.

Get daily content like this in your inbox!

Subscribe