Strings are fixed-size, though. A string is a pointer and a length.
It's true that you can't use a slice as a map key, though, even though slices are also fixed-size (pointer, length, and capacity). As I recall, the argument is that the equality rules for slices are unclear. (maps and funcs can't be used as keys either, for the same reason: they're not comparable.) Is a 0-length slice equal to a nil slice? Is a slice with len 3, cap 3 equal to a slice with len 3, cap 4?
In practice, this is rarely a problem. It most commonly comes up when you want to use []byte as a key, in which case you can convert the []byte to a string. This overhead of this conversion (specifically when it occurs in the context of a map key) has been optimized away for a few versions now.
Maybe "fixed size" was the wrong way to phrase it. What I meant is that a string points to an unlimited amount of data and all of that unlimited amount of data is taken into account when deciding equality of strings. And my question should have been, is string the only datatype with that feature?
If it is, it means Go is like Lua, where if you want to use any compound data structure as a key in a map, you either marshall it to a string or you implement your own hashtable.
In Python you are allowed to use tuples of immutable objects as keys, for example. Much nicer than serializing everything to strings.
As for "in practice this is rarely a problem", I agree, but prefer languages where the standard library doesn't have these arbitrary limitations. For example I might want to implement multivariate sparse polynomials as maps from exponent tuples to coefficients (the polynomial 3 x^2 y^3 z + 7 x y z^4 corresponds to the map {(2,3,1): 3, (1,1,4): 7}). That's straightforward in Python but awkward in Go (in Go I might be tempted to just set a maximum number of variables and use arrays or exponents as keys).
Oh, cool! This still doesn't quite get rid of my complaint since the size of an array must be known at compile time, but it's good that they don't all have to be the same size.
Would it be too hard to just compare arbitrary slices and arrays based on the contents of said data structures?
Converting arbitrary bytes to strings should fail at least some times, since not all byte sequences are valid UTF-8, and afaiu, in Go, the string type should always contain valid UTF-8.
Go strings do not need to contain valid UTF-8, although in practice they usually do. A 'range' loop over a string will loop over its UTF-8 codepoints, but in general, a string can contain arbitrary binary data. See https://golang.org/pkg/builtin/#string
It's true that you can't use a slice as a map key, though, even though slices are also fixed-size (pointer, length, and capacity). As I recall, the argument is that the equality rules for slices are unclear. (maps and funcs can't be used as keys either, for the same reason: they're not comparable.) Is a 0-length slice equal to a nil slice? Is a slice with len 3, cap 3 equal to a slice with len 3, cap 4?
In practice, this is rarely a problem. It most commonly comes up when you want to use []byte as a key, in which case you can convert the []byte to a string. This overhead of this conversion (specifically when it occurs in the context of a map key) has been optimized away for a few versions now.