ruk·si

🐹 Go
Strings

Updated at 2014-01-20 11:45

Go has good native libraries for working with strings.

String is a slice of bytes []byte. String itself does not care anything about encodings, they are just bytes and a byte is alias for uint8. Output depends how your read them, but you can check if a string is UTF-8 with ValidString() in unicode/utf8. Go source code is always UTF-8.

package main

import "fmt"

func main() {
    const text = "\xbd\xb2\x3d\xbc\x20\xe2\x8c\x98"
    fmt.Println(text)
    for i := 0; i < len(text); i++ {
        // Print in hexadecimal format.
        fmt.Printf("%x ", text[i])
    }
    fmt.Printf("\n\n")

    // Note that some characters are more than one byte.
    const placeOfInterest = `⌘`
    fmt.Printf("%s", placeOfInterest)
    fmt.Printf("\n")
    for i := 0; i < len(placeOfInterest); i++ {
        fmt.Printf("%x ", placeOfInterest[i])
    }
    fmt.Printf("\n\n")

    // To interate over characters, use range.
    const nihongo = "日本語"
    for index, runeValue := range nihongo {
        fmt.Printf("%#U starts at byte position %d\n", runeValue, index)
    }
}

len on strings tells the number of bytes, not characters. RuneCountInString() in unicode/utf8 tells the number of runes, not characters.

package main

import (
    "fmt"
    "unicode/utf8"
)

func main() {
    text := "♥"
    fmt.Println(len(text))                       // => 3
    fmt.Println(utf8.RuneCountInString(text))    // => 1
    text2 := "é"
    fmt.Println(len(text2))                      // => 3
    fmt.Println(utf8.RuneCountInString(text2))   // => 2
}

__Use conversions to do precise operations on strings. Converting between string and []byte is very efficient.

package main

import "fmt"

func main() {
    x := "text"
    xbytes := []byte(x)
    xbytes[0] = 'T'
    fmt.Println(string(xbytes)) // Text
}

Strings can be raw literals or interpreted literals. Raw literals use backticks ``, and may contain newlines and backslashes. Interpreted literals use double quotes "", where all special characters must be escaped.

package main

import "fmt"

func main() {
    // These are equal.
    fmt.Println(`abc`)
    fmt.Println("abc")

    // These are equal.
    fmt.Println(`日本語`)
    fmt.Println("日本語")

    // These are equal.
    fmt.Println(`\n
\n`)
    fmt.Println("\\n\n\\n")

    // These are equal.
    fmt.Println(`Hello, world!
`)
    fmt.Println("Hello, world!\n")
}

String formatting using fmt.

package main

import (
    "fmt"
    "os"
)

type point struct {
    x, y int
}

func main() {

    // fmt.Printf sends formatted string to os.Stdout.
    fmt.Printf("%t\n", true) // %t, print boolean.

    fmt.Printf("%b\n", 123) // %b, print binary, base 2.
    fmt.Printf("%d\n", 123) // %d, print number, base 10.
    fmt.Printf("%c\n", 123) // %c, print Unicode character
    fmt.Printf("%x\n", 123) // %x, print hex, base 16, lowercase.
    fmt.Printf("%X\n", 123) // %x, print hex, base 16, uppercase.

    fmt.Printf("%f\n", 78.9) // %f, print float, no exponents.
    fmt.Printf("%e\n", 78.9) // %e, print float using exponents, lowercase e.
    fmt.Printf("%E\n", 78.9) // %E, print float using exponents, uppercase e.
    fmt.Printf("%.2f %.2f\n", 1.2, 3.456) // %.2f, print with 2 decimals.

    fmt.Printf("%s\n", "Hello!") // %s, print string.
    fmt.Printf("%q\n", "Hello!") // %q, print quoted string with escapes.
    fmt.Printf("%x\n", "Hello!") // %x, print hex.

    fmt.Printf("|%6d|%6d|\n", 12, 345) // %6d, print with space padding to 6.
    fmt.Printf("|%6s|%6s|\n", "foo", "b") // %6s, print with space padding to 6.
    fmt.Printf("|%-6d|%-6d|\n", 12, 345) // %-6d, print aligned left.
    fmt.Printf("|%-6s|%-6s|\n", "foo", "b") // %-6s, print aligned left.

    p := point{1, 2}
    fmt.Printf("%v\n", p) // %v, print value.
    fmt.Printf("%+v\n", p) // %+v, print value with field names.
    fmt.Printf("%#v\n", p) // %#v, print code that produces the value.
    fmt.Printf("%T\n", p) // %T, print type of a value.
    fmt.Printf("%p\n", &p) // %p, print pointer.

    // fmt.Sprintf returns the formatted string.
    s := fmt.Sprintf("a %s", "string")
    fmt.Println(s)

    // fmt.Fprintf forwards the formatted string to the given io.Writer.
    fmt.Fprintf(os.Stderr, "an %s\n", "error")

    // fmt.Errorf returns an error with the formatted string.
    err := fmt.Errorf("user with id %d not found.", 101)
    fmt.Println(err)
}

String related functions are mostly in strings.

package main

import (
    "fmt"
    "strings"
)

var p = fmt.Println

func main() {
    p("Contains:  ", strings.Contains("test", "es")) // => true
    p("Count:     ", strings.Count("test", "t") // => 2
    p("HasPrefix: ", strings.HasPrefix("test", "te")) // => true
    p("HasSuffix: ", strings.HasSuffix("test", "st")) // => true
    p("Index:     ", strings.Index("test", "e")) // => 1
    p("Join:      ", strings.Join([]string{"a", "b"}, "-")) // => a-b
    p("Repeat:    ", strings.Repeat("a", 5)) // => aaaaa
    p("Replace:   ", strings.Replace("foo", "o", "0", -1)) // => f00
    p("Replace:   ", strings.Replace("foo", "o", "0", 1)) // => f0o
    p("Split:     ", strings.Split("a-b-c-d-e", "-")) // => [a b c d e]
    p("ToLower:   ", strings.ToLower("TEST")) // => test
    p("ToUpper:   ", strings.ToUpper("test"))// => TEST
    p()
    p("Len: ", len("hello")) // => 5
    p("Char:", "hello"[1]) // => 101
}

Sources