Lesson 4
String Handling and Character Operations in Go
Lesson Overview

Welcome to an engaging session on Go programming! Today, we'll explore how to efficiently handle string data in Go. Whether you're building a web scraper or developing a text-based algorithm for analyzing user reviews, effectively processing strings is essential. In this lesson, we'll focus on traversing and manipulating strings in Go. We'll cover string indexing, rune handling, and character operations using Go functions.

Our main goal is to become proficient in using Go loops and string functions with a specific emphasis on strings. You'll learn how Go handles string data, allowing you to perform operations on each character seamlessly.

Working with Runes and Unicode in Characters

In Go, strings are encoded using UTF-8, and characters are typically managed using the rune type, which can be thought of as Go's version of a char. A rune is an alias for int32 and represents a Unicode code point, allowing you to seamlessly work with both ASCII and non-ASCII characters.

To convert a character into its Unicode code point, you can simply assign it to a variable of type rune. Go automatically infers the type as int32, so no explicit casting is needed:

Go
1package main 2 3import "fmt" 4 5 6func main() { 7 var c rune = 'A' 8 var unicodeVal int32 = c // No explicit casting is needed 9 // unicodeVal := c // This would work as well 10 fmt.Printf("The Unicode value of %c is: %d\n", c, unicodeVal) 11}

Here, c is variable of type rune, representing the character 'A'. The variable unicodeVal holds the Unicode code point value of c because rune is an int32.

Similarly, you can convert a Unicode code point back to its corresponding character by assigning it to a rune:

Go
1package main 2 3import "fmt" 4 5 6func main() { 7 var unicodeVal int32 = 65 8 c := rune(unicodeVal) 9 fmt.Printf("The character for Unicode value %d is: %c\n", unicodeVal, c) 10}

In this example, unicodeVal is of type int32 (underlying type of rune), and the conversion back to a character using rune allows you to handle the character representation seamlessly.

Manipulating runes can be valuable when dealing with character transformations. Functions from Go's unicode package can help with converting between uppercase and lowercase while accommodating the full spectrum of Unicode characters.

String Indexing Reminder

Go strings use a zero-based indexing system like many other programming languages. However, due to UTF-8 encoding, a single character (rune) might occupy more than one byte. Use runes for accurate character (rather than byte) indexing.

Here’s an example:

Go
1package main 2 3import ( 4 "fmt" 5 "unicode/utf8" 6) 7 8func main() { 9 var text string = "Hello, Go!" 10 if utf8.RuneCountInString(text) >= 10 { 11 runes := []rune(text) // convert string into slice of runes 12 tenthChar := runes[9] 13 fmt.Printf("The tenth character is: %c\n", tenthChar) 14 } else { 15 fmt.Println("The string is too short!") 16 } 17}

In this code:

  • We initialize a string variable text with the value "Hello, Go!".
  • utf8.RuneCountInString(text) is used to count the number of runes (characters) in the string.
  • If the string has 10 or more characters, it gets converted into a slice of runes. Converting the string into a slice of runes ensures that we correctly handle multi-byte characters, allowing for accurate rune-based indexing to access the 10th character
  • The variable tenthChar is assigned the 10th rune (index 9) from the rune slice.
Character Operations

Let's explore character operations in Go using the unicode package. These functions allow you to perform common character transformations and checks. For example, let's try checking different character properties:

Go
1package main 2 3import ( 4 "fmt" 5 "unicode" 6) 7 8func main() { 9 fmt.Printf("Is 'a' lowercase? %t\n", unicode.IsLower('a')) // Prints: true 10 fmt.Printf("Is 'B' lowercase? %t\n", unicode.IsLower('B')) // Prints: false 11 12 fmt.Printf("Is 'a' uppercase? %t\n", unicode.IsUpper('a')) // Prints: false 13 fmt.Printf("Is 'B' uppercase? %t\n", unicode.IsUpper('B')) // Prints: true 14 15 fmt.Printf("Is 'C' a letter? %t\n", unicode.IsLetter('C')) // Prints: true 16 fmt.Printf("Is '+' a letter? %t\n", unicode.IsLetter('+')) // Prints: false 17 18 fmt.Printf("Is '9' a digit? %t\n", unicode.IsDigit('9')) // Prints: true 19 fmt.Printf("Is 'D' a digit? %t\n", unicode.IsDigit('D')) // Prints: false 20 21 fmt.Printf("Is '6' alphanumeric? %t\n", unicode.IsLetter('6') || unicode.IsDigit('6')) // Prints: true 22 fmt.Printf("Is '?' alphanumeric? %t\n", unicode.IsLetter('?') || unicode.IsDigit('?')) // Prints: false 23 24 fmt.Printf("Is ' ' a space? %t\n", unicode.IsSpace(' ')) // Prints: true 25 fmt.Printf("Is '\n' a space? %t\n", unicode.IsSpace('\n')) // Prints: true 26 27 fmt.Printf("Is '?' punctuation? %t\n", unicode.IsPunct('?')) // Prints: true 28}
Lesson Summary and Practice

Great job! We’ve covered string handling in Go by looping over strings, managing string and rune indices, and leveraging the power of Go’s packages for character operations. You’ve seen how Go's UTF-8 encoding enables easy handling of diverse characters, making string processing efficient and versatile.

The skills you’ve learned are applicable to numerous real-world scenarios, from building chat applications and parsers to creating intelligent algorithms. Keep practicing these concepts to solidify your understanding, and continue exploring the exciting capabilities of Go! Your journey is just beginning — looking forward to seeing you in upcoming sessions!

Enjoy this lesson? Now it's time to practice with Cosmo!
Practice is how you turn knowledge into actual skills.