Skip to main content
โšก Calmops

Go Strings: Creation, Manipulation, Formatting

Go Strings: Creation, Manipulation, Formatting

Strings are fundamental to any programming language. Go treats strings as immutable sequences of bytes, but provides powerful tools for working with them. This guide covers string creation, manipulation, formatting, and best practices.

String Basics

Creating Strings

package main

import "fmt"

func main() {
    // String literal
    s1 := "Hello, World!"
    
    // Raw string literal (preserves escape sequences)
    s2 := `Line 1
Line 2
Line 3`
    
    // Empty string
    s3 := ""
    
    // String from rune
    s4 := string('A')
    
    // String from bytes
    s5 := string([]byte{72, 101, 108, 108, 111})
    
    fmt.Println(s1)
    fmt.Println(s2)
    fmt.Println(s3)
    fmt.Println(s4)
    fmt.Println(s5)
}

String Properties

package main

import "fmt"

func main() {
    s := "Hello"
    
    // Length in bytes
    fmt.Println(len(s))  // 5
    
    // Access byte at index
    fmt.Println(s[0])    // 72 (ASCII for 'H')
    fmt.Println(s[1])    // 101 (ASCII for 'e')
    
    // Iterate over bytes
    for i := 0; i < len(s); i++ {
        fmt.Printf("%c ", rune(s[i]))
    }
    // Output: H e l l o
    
    // Iterate over runes
    for _, r := range s {
        fmt.Printf("%c ", r)
    }
    // Output: H e l l o
}

String Manipulation

Basic Operations

package main

import (
    "fmt"
    "strings"
)

func main() {
    s := "Hello, World!"
    
    // Concatenation
    result := s + " How are you?"
    fmt.Println(result)
    
    // Substring
    fmt.Println(s[0:5])      // "Hello"
    fmt.Println(s[7:])       // "World!"
    fmt.Println(s[:5])       // "Hello"
    
    // Contains
    fmt.Println(strings.Contains(s, "World"))  // true
    
    // Index
    fmt.Println(strings.Index(s, "World"))     // 7
    fmt.Println(strings.LastIndex(s, "l"))     // 10
    
    // Count
    fmt.Println(strings.Count(s, "l"))         // 3
}

String Transformation

package main

import (
    "fmt"
    "strings"
)

func main() {
    s := "Hello, World!"
    
    // Case conversion
    fmt.Println(strings.ToLower(s))    // "hello, world!"
    fmt.Println(strings.ToUpper(s))    // "HELLO, WORLD!"
    fmt.Println(strings.Title(s))      // "Hello, World!"
    
    // Trimming
    s2 := "  hello  "
    fmt.Println(strings.TrimSpace(s2))           // "hello"
    fmt.Println(strings.Trim(s2, " "))           // "hello"
    fmt.Println(strings.TrimPrefix(s, "Hello"))  // ", World!"
    fmt.Println(strings.TrimSuffix(s, "!"))      // "Hello, World"
    
    // Replace
    fmt.Println(strings.Replace(s, "World", "Go", 1))  // "Hello, Go!"
    fmt.Println(strings.ReplaceAll(s, "l", "L"))       // "HeLLo, WorLd!"
}

Splitting and Joining

package main

import (
    "fmt"
    "strings"
)

func main() {
    // Split
    s := "apple,banana,cherry"
    parts := strings.Split(s, ",")
    fmt.Println(parts)  // [apple banana cherry]
    
    // Split with limit
    parts2 := strings.SplitN(s, ",", 2)
    fmt.Println(parts2)  // [apple banana,cherry]
    
    // Split on whitespace
    s2 := "hello   world   go"
    parts3 := strings.Fields(s2)
    fmt.Println(parts3)  // [hello world go]
    
    // Join
    joined := strings.Join(parts, " - ")
    fmt.Println(joined)  // "apple - banana - cherry"
}

String Formatting

Using fmt Package

package main

import "fmt"

func main() {
    name := "Alice"
    age := 30
    height := 5.7
    
    // Printf - formatted output
    fmt.Printf("Name: %s, Age: %d, Height: %.1f\n", name, age, height)
    
    // Sprintf - formatted string
    result := fmt.Sprintf("Name: %s, Age: %d", name, age)
    fmt.Println(result)
}

Format Verbs

package main

import "fmt"

func main() {
    // String and character
    fmt.Printf("%s\n", "hello")      // hello
    fmt.Printf("%q\n", "hello")      // "hello" (quoted)
    fmt.Printf("%c\n", 65)           // A (character)
    
    // Integer
    fmt.Printf("%d\n", 42)           // 42 (decimal)
    fmt.Printf("%x\n", 255)          // ff (hexadecimal)
    fmt.Printf("%o\n", 8)            // 10 (octal)
    fmt.Printf("%b\n", 5)            // 101 (binary)
    
    // Float
    fmt.Printf("%f\n", 3.14)         // 3.140000
    fmt.Printf("%.2f\n", 3.14159)    // 3.14 (2 decimal places)
    fmt.Printf("%e\n", 1000.0)       // 1.000000e+03 (scientific)
    fmt.Printf("%g\n", 1000.0)       // 1000 (general format)
    
    // Boolean
    fmt.Printf("%v\n", true)         // true
    fmt.Printf("%t\n", true)         // true
    
    // General
    fmt.Printf("%v\n", 42)           // 42 (value)
    fmt.Printf("%T\n", 42)           // int (type)
    fmt.Printf("%#v\n", []int{1,2})  // []int{1, 2} (Go syntax)
}

Width and Precision

package main

import "fmt"

func main() {
    // Width
    fmt.Printf("|%5s|\n", "hi")      // |   hi|
    fmt.Printf("|%-5s|\n", "hi")     // |hi   |
    fmt.Printf("|%05d|\n", 42)       // |00042|
    
    // Precision
    fmt.Printf("%.2f\n", 3.14159)    // 3.14
    fmt.Printf("%.5s\n", "hello")    // hello
    
    // Width and precision
    fmt.Printf("%10.2f\n", 3.14159)  // "      3.14"
}

Runes and Bytes

Understanding Runes

package main

import "fmt"

func main() {
    // Rune is an alias for int32
    r := 'A'
    fmt.Printf("%T\n", r)  // int32
    fmt.Println(r)         // 65
    
    // String to runes
    s := "Hello"
    runes := []rune(s)
    fmt.Println(runes)     // [72 101 108 108 111]
    
    // Runes to string
    s2 := string(runes)
    fmt.Println(s2)        // Hello
    
    // Iterate over runes
    for i, r := range s {
        fmt.Printf("%d: %c (%d)\n", i, r, r)
    }
}

Working with Bytes

package main

import "fmt"

func main() {
    // String to bytes
    s := "Hello"
    bytes := []byte(s)
    fmt.Println(bytes)     // [72 101 108 108 111]
    
    // Bytes to string
    s2 := string(bytes)
    fmt.Println(s2)        // Hello
    
    // Modify bytes
    bytes[0] = 'J'
    s3 := string(bytes)
    fmt.Println(s3)        // Jello
}

Unicode Handling

package main

import (
    "fmt"
    "unicode"
    "unicode/utf8"
)

func main() {
    s := "Hello, ไธ–็•Œ"
    
    // Length in bytes vs runes
    fmt.Println(len(s))                    // 13 (bytes)
    fmt.Println(utf8.RuneCountInString(s)) // 9 (runes)
    
    // Check character properties
    fmt.Println(unicode.IsLetter('a'))     // true
    fmt.Println(unicode.IsDigit('5'))      // true
    fmt.Println(unicode.IsSpace(' '))      // true
    
    // Case conversion
    fmt.Println(unicode.ToLower('A'))      // 97
    fmt.Println(unicode.ToUpper('a'))      // 65
}

String Comparison

package main

import (
    "fmt"
    "strings"
)

func main() {
    s1 := "hello"
    s2 := "hello"
    s3 := "world"
    
    // Equality
    fmt.Println(s1 == s2)  // true
    fmt.Println(s1 == s3)  // false
    
    // Case-insensitive comparison
    fmt.Println(strings.EqualFold("Hello", "hello"))  // true
    
    // Lexicographic comparison
    fmt.Println(s1 < s3)   // true (h < w)
    fmt.Println(strings.Compare(s1, s3))  // -1 (s1 < s3)
}

String Building

Using strings.Builder

package main

import (
    "fmt"
    "strings"
)

func main() {
    var sb strings.Builder
    
    sb.WriteString("Hello")
    sb.WriteString(", ")
    sb.WriteString("World")
    sb.WriteRune('!')
    
    result := sb.String()
    fmt.Println(result)  // Hello, World!
}

Concatenation Performance

package main

import (
    "fmt"
    "strings"
)

func main() {
    // โŒ Bad: String concatenation in loop
    var result string
    for i := 0; i < 1000; i++ {
        result += fmt.Sprintf("Item %d\n", i)
    }
    
    // โœ… Good: Using strings.Builder
    var sb strings.Builder
    for i := 0; i < 1000; i++ {
        fmt.Fprintf(&sb, "Item %d\n", i)
    }
    result = sb.String()
    
    fmt.Println(result)
}

Common String Patterns

Checking String Properties

package main

import (
    "fmt"
    "strings"
)

func main() {
    s := "hello"
    
    // Check if empty
    if s == "" {
        fmt.Println("Empty string")
    }
    
    // Check if starts/ends with
    if strings.HasPrefix(s, "he") {
        fmt.Println("Starts with 'he'")
    }
    
    if strings.HasSuffix(s, "lo") {
        fmt.Println("Ends with 'lo'")
    }
    
    // Check if contains
    if strings.Contains(s, "ll") {
        fmt.Println("Contains 'll'")
    }
}

String Validation

package main

import (
    "fmt"
    "regexp"
    "strings"
)

func main() {
    // Email validation (simple)
    email := "[email protected]"
    if strings.Contains(email, "@") && strings.Contains(email, ".") {
        fmt.Println("Valid email format")
    }
    
    // Regex validation
    re := regexp.MustCompile(`^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`)
    if re.MatchString(email) {
        fmt.Println("Valid email")
    }
}

Best Practices

โœ… Good Practices

  1. Use strings.Builder for concatenation - More efficient than +
  2. Use raw strings for multi-line text - Preserves formatting
  3. Use fmt.Sprintf for formatting - Cleaner than concatenation
  4. Handle Unicode properly - Use runes for character operations
  5. Use strings package functions - Optimized and tested
  6. Validate input strings - Check for empty, length, format
  7. Use immutability - Strings are immutable, design accordingly

โŒ Anti-Patterns

// โŒ Bad: String concatenation in loop
var result string
for i := 0; i < 1000; i++ {
    result += "Item " + strconv.Itoa(i) + "\n"
}

// โœ… Good: Use strings.Builder
var sb strings.Builder
for i := 0; i < 1000; i++ {
    fmt.Fprintf(&sb, "Item %d\n", i)
}

// โŒ Bad: Ignoring Unicode
for i := 0; i < len(s); i++ {
    // Doesn't work correctly with multi-byte characters
}

// โœ… Good: Use range for runes
for _, r := range s {
    // Works correctly with Unicode
}

Summary

Go strings are powerful and flexible:

  • Create strings with literals or conversion
  • Manipulate with strings package functions
  • Format with fmt package
  • Handle Unicode with runes
  • Use strings.Builder for efficient concatenation
  • Follow best practices for performance and correctness

Master these string operations for effective Go programming.

Comments