Strings in Golang

Strings are essential in every programming language. Go is no different here. We will see how to initialize and use those strings.

Initializing Strings in Golang

We can initialize strings just like any other data-type. String concatenation can be done effortlessly.

package main

import (
	"fmt"
)

func main() {
	var hello string = "Hello, " // init
	name := "Dan"
	exclamation := "!"
	
	var result = hello + name + exclamation // concatenation
	fmt.Println(result)   // prints "Hello, Dan!"
}

Accessing by index

Strings in Go can be accessed just like an array or a slice. Each byte of string can be accessed in that way.

Below is a program showing just that.

package main

import (
	"fmt"
)

func main() {
	greet := "Hello World"
	fmt.Printf("%c\n", greet[0])  // prints H
	fmt.Printf("%x\n", greet[0])  // prints 48 
}

Length of a string

To get the length of a string we use the len() function.

package main

import (
	"fmt"
)

func main() {
	fmt.Println(len("Hello, world")) // prints 12
}

Comparing Strings in Go

You can compare strings as well. String comparison returns a value of either 0, 1 or -1.

package main

import (
	"fmt"
)

func main() {
	var hello string = "Hi"
	var hello2 string = "Hello"
	fmt.Println(hello == hello2) // prints false
	fmt.Println(hello > hello2) // prints true
	fmt.Println(hello < hello2) // prints false
}

Runes in Go

Runes are of type int32. They represent the Unicode code point. So, that means for each code point any value can be taken by a rune depending on the situation. Let’s see how to use runes.

package main

import (
	"fmt"
)

func main() {
	s := "This is an example."
	runes := []rune(s)
	
	fmt.Println(len(runes)) // prints 26
	
	fmt.Printf("%c", runes[0])   // prints T
	
	for i := 0; i<len(s); i++ {
		// "%U" prints Unicode equivalent
		fmt.Printf("%U ", s[i]) // prints "TU+0054 U+0068 U+0069 U+0073 U+0020 U+0069 U+0073 U+0020 U+0061 U+006E U+0020 U+0065 U+0078 U+0061 U+006D U+0070 U+006C U+0065 U+002E "
	}
}

Iterating over a string

To iterate over a string we use loops. Let’s see what are the ways we do that.

1. Using for loop

Here is an example using naive for loop to iterate over a string.

package main

import (
	"fmt"
)

func main() {
	s := "example string"
	
	for i := 0; i < len(s); i++ {
		fmt.Printf("%c ", s[i])   // prints "e x a m p l e   s t r i n g "
	}
}

2. Using a range-based for loop

Range iterates over slices or arrays. For a string range iterates over each byte of it.

package main

import (
	"fmt"
)

func main() {
	s := "example string"
	
	for i, c := range s {
		fmt.Printf("%c->%d ", c, i)   // prints "e->0 x->1 a->2 m->3 p->4 l->5 e->6  ->7 s->8 t->9 r->10 i->11 n->12 g->13 "
	}
}

Constructing a string

Other than initializing directly strings can be constructed in many ways. Here we will see how to construct a string from slices of bytes and runes.

1. From a slice of bytes

Strings can be constructed from a slice of bytes. Since essentially a string is just a slice of bytes. Here we can see how to convert the slice to a string.

package main

import (
	"fmt"
)

func main() {
	stringBytes := []byte{72, 101, 108, 108, 111}
	stringCreated := string(stringBytes)
	fmt.Println(stringCreated)  // prints "Hello"
}

2. From a slice of runes

Runes in Go are just Unicode code points. That means they also can be used instead of bytes to do the same thing.

package main

import (  
    "fmt"
)

func main() {  
    runesOfString := []rune{0x0048, 0x0065, 0x006C, 0x006C, 0x006F}
    s := string(runesOfString)
    fmt.Println(s) // prints "Hello"
}

Strings immutability

Strings are immutable in nature. You cannot assign a value to a string after it has been assigned. Here is an example illustrating that.

package main

import (  
    "fmt"
)

func main() {  
    runesOfString := []rune{0x0048, 0x0065, 0x006C, 0x006C, 0x006F}
    s := string(runesOfString)
    fmt.Println(s) // prints "Hello"
}

To mutate a string we need to first convert into an array of runes.

package main

import (  
    "fmt"
)

func main() {  
	s := "A string"
	// s[0] = "B"      // throws error "cannot assign to s[0]"
	
	// convert to rune slice
	runes := []rune(s)
	
	//mutate value
	runes[0] = 'B'
	
	s = string(runes) // convert to string again
	
	fmt.Println(s)   // prints "B string"
}

In this way, values can be modified in a string.