Go gotchas: rune is the new char

Let’s talk about S#. What, you know only about C#, or maybe F#?

That’s German double S — ß, which may be called “eszett” or “sharp S”.

If you've been to Munich, you've probably visited Maximilianstraße. It has this “sharp S” at the end.

Maximilianstraße is quite a long word. Not sure how many character it has. Let’s try to count them using Go, and, simply for comparison, horrendous JavaScript.

I’ll start with JavaScript:

console.log(`Maximilianstraße`.length) //16
console.log(`Maximilianstraße`[1]) //ß

Now same with Go:

word := `Maximilianstraße`
wordLen := len(word)
fmt.Println(wordLen) //17

That’s strange. JavaScript counted only 16 characters.

Well, doesn’t matter. Let’s print only our “sharp S”:

fmt.Println(word[wordLen-2:wordLen-1]) //�

Wait, what?

Ok, I’ll count it by hand…

fmt.Println(word[14:15]) //�
fmt.Println(word[15:16]) //�

Where’s my ß?

Oh, here it is. Why does it take two characters, though?

fmt.Println(word[14:16]) //ß

As with many other matters, Go support of Unicode is somewhat… lacking. Go is okay with Unicode. Doesn't have anything against it. But it will not vote for it on the next Unicode vs UTF-8 elections (wait, they’re not the same?!)

So, when dealing with string slices, as we did now, we need to work harder. Consider this:

wordLen = utf8.RuneCountInString(word)
fmt.Println(wordLen) //16

Now to get our letter out, we convert string to slice of runes. Runes are the “proper characters”, as we think of them.

utf8Runes := []rune(word)
sharpS := string(utf8Runes[14:15])
fmt.Println(sharpS) //ß

Interestingly, though, for loop is aware of those quirks:

i := 0for _, _ = range word {
i++
}
fmt.Println(i) //16for i, c := range word {
fmt.Printf("%d:%c ", i, c)
}
// 0:M 1:a 2:x 3:i 4:m 5:i 6:l 7:i 8:a 9:n 10:s 11:t 12:r 13:a 14:ß 16:e

Note how 15th index is smartly skipped in the code above.

Remember this next time you plan to work with possibly Unicode slices in Go.

You can see the entire example on my GitHub:

And play with it on Go Playground: https://play.golang.org/p/VfucB9MoKs

Solutions Architect @Depop, author of “Hands-on Design Patterns with Kotlin” book and “Web Development with Kotlin” course

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

What is Makefile and how to use it?

How to create and update a Deno module / plugin ?

Sorting of HashMAP based on Value Using JAVA

Midnight Casino 240x320 Jar

Jar

WebGL Build Debugging

Technology is Delivering…..Are You?

Uploading a Python package to PyPi

Multi-chain NFT infrastructure “Hokusai” announces the start of support for BNB Chain, Astar, and…

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Alexey Soshin

Alexey Soshin

Solutions Architect @Depop, author of “Hands-on Design Patterns with Kotlin” book and “Web Development with Kotlin” course

More from Medium

Not such a hard worker

The Goodbye 2021, Hello 2022

Review for “A View of the Parallel Computing Landscape”

Open Sourcing the Netflix Domain Graph Service Framework: GraphQL for Spring Boot