Converting rune slices to strings

March 8, 2024

Yesterday we started through the list of rules and special cases for converting to and from string types. Let’s continue…

Conversions to and from a string type

  1. Converting a slice of runes to a string type yields a string that is the concatenation of the individual rune values converted to strings.
string([]rune{0x767d, 0x9d6c, 0x7fd4})   // "\u767d\u9d6c\u7fd4" == "白鵬翔"
string([]rune{})                         // ""
string([]rune(nil))                      // ""

type runes []rune
string(runes{0x767d, 0x9d6c, 0x7fd4})    // "\u767d\u9d6c\u7fd4" == "白鵬翔"

type myRune rune
string([]myRune{0x266b, 0x266c})         // "\u266b\u266c" == "♫♬"
myString([]myRune{0x1f30e})              // "\U0001f30e" == "🌎"

I think this one is pretty intuitive. Well, once you grasp Go’s concept of runes anyway. Although even this isn’t entirely intuitive, if you’re not yet comfortable with Unicode. It’s possible to have multiple runes that render as a single visible character. In such a case, a slice of runes may display differently than the slice concatenated into a string.

r := []rune{'у', '̆'}
s := string(r)
fmt.Printf("%q => %q\n", r, s) // ['у' '̆'] => "ў"
fmt.Println(len(r), len(s), utf8.RuneCountInString(s)) // 2 4 2

So what if you want to know the “visual length” of such a string? What function would return 1 as the length?

The third-party package github.com/rivo/uniseg might be of help here. The GraphemeClusterCount function can be used to count the number of grapheme clusters, the technical term for what we care about in this case.

import "github.com/rivo/uniseg"

fmt.Println(uniseg.GraphemeClusterCount(s)) // 1

Quotes from The Go Programming Language Specification Language version go1.22 (Feb 6, 2024)


Share this

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

Unsure? Browse the archive .

Get daily content like this in your inbox!

Subscribe