Skip to main content
โšก Calmops

Go Standard Library: fmt, strings, strconv

Go Standard Library: fmt, strings, strconv

The fmt, strings, and strconv packages are fundamental to Go programming. This guide covers their most useful functions and patterns.

fmt Package - Formatting

package main

import "fmt"

func main() {
    // Print to stdout
    fmt.Print("Hello")
    fmt.Print(" ")
    fmt.Println("World")
    
    // Printf with format
    fmt.Printf("Number: %d, String: %s\n", 42, "hello")
    
    // Sprintf returns string
    s := fmt.Sprintf("Value: %v", 42)
    fmt.Println(s)
}

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"
}

Scanning Input

package main

import (
    "fmt"
)

func main() {
    var name string
    var age int
    
    // Scan from stdin
    fmt.Print("Enter name: ")
    fmt.Scan(&name)
    
    fmt.Print("Enter age: ")
    fmt.Scan(&age)
    
    fmt.Printf("Name: %s, Age: %d\n", name, age)
}

strings Package - String Manipulation

Basic Operations

package main

import (
    "fmt"
    "strings"
)

func main() {
    s := "Hello, World!"
    
    // Length
    fmt.Println(len(s))  // 13
    
    // 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
}

Case Conversion

package main

import (
    "fmt"
    "strings"
)

func main() {
    s := "Hello, World!"
    
    fmt.Println(strings.ToLower(s))    // hello, world!
    fmt.Println(strings.ToUpper(s))    // HELLO, WORLD!
    fmt.Println(strings.Title(s))      // Hello, World!
}

Trimming

package main

import (
    "fmt"
    "strings"
)

func main() {
    s := "  hello world  "
    
    fmt.Println(strings.TrimSpace(s))           // hello world
    fmt.Println(strings.Trim(s, " "))           // hello world
    fmt.Println(strings.TrimPrefix("hello", "he"))  // llo
    fmt.Println(strings.TrimSuffix("hello", "lo"))  // hel
}

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]
    
    // Fields (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
}

Replace

package main

import (
    "fmt"
    "strings"
)

func main() {
    s := "hello world hello"
    
    // Replace first n occurrences
    fmt.Println(strings.Replace(s, "hello", "hi", 1))
    // hi world hello
    
    // Replace all occurrences
    fmt.Println(strings.ReplaceAll(s, "hello", "hi"))
    // hi world hi
}

String Building

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!
}

strconv Package - Type Conversion

String to Integer

package main

import (
    "fmt"
    "strconv"
)

func main() {
    // String to int
    i, err := strconv.Atoi("42")
    if err != nil {
        fmt.Println("Error:", err)
    }
    fmt.Println(i)  // 42
    
    // String to int64
    i64, err := strconv.ParseInt("42", 10, 64)
    if err != nil {
        fmt.Println("Error:", err)
    }
    fmt.Println(i64)  // 42
    
    // String to uint64
    u64, err := strconv.ParseUint("42", 10, 64)
    if err != nil {
        fmt.Println("Error:", err)
    }
    fmt.Println(u64)  // 42
}

Integer to String

package main

import (
    "fmt"
    "strconv"
)

func main() {
    // Int to string
    s := strconv.Itoa(42)
    fmt.Println(s)  // "42"
    
    // Int64 to string
    s2 := strconv.FormatInt(42, 10)
    fmt.Println(s2)  // "42"
    
    // Different bases
    fmt.Println(strconv.FormatInt(255, 16))  // ff (hex)
    fmt.Println(strconv.FormatInt(8, 8))     // 10 (octal)
    fmt.Println(strconv.FormatInt(5, 2))     // 101 (binary)
}

String to Float

package main

import (
    "fmt"
    "strconv"
)

func main() {
    // String to float64
    f, err := strconv.ParseFloat("3.14", 64)
    if err != nil {
        fmt.Println("Error:", err)
    }
    fmt.Println(f)  // 3.14
    
    // String to float32
    f32, err := strconv.ParseFloat("3.14", 32)
    if err != nil {
        fmt.Println("Error:", err)
    }
    fmt.Println(float32(f32))  // 3.14
}

Float to String

package main

import (
    "fmt"
    "strconv"
)

func main() {
    // Float to string
    s := strconv.FormatFloat(3.14, 'f', 2, 64)
    fmt.Println(s)  // "3.14"
    
    // Different formats
    fmt.Println(strconv.FormatFloat(3.14, 'e', 2, 64))  // 3.14e+00
    fmt.Println(strconv.FormatFloat(3.14, 'g', 2, 64))  // 3.1
}

String to Boolean

package main

import (
    "fmt"
    "strconv"
)

func main() {
    // String to bool
    b, err := strconv.ParseBool("true")
    if err != nil {
        fmt.Println("Error:", err)
    }
    fmt.Println(b)  // true
    
    // Accepted values: 1, t, T, TRUE, true, True, 0, f, F, FALSE, false, False
    b2, _ := strconv.ParseBool("1")
    fmt.Println(b2)  // true
}

Practical Examples

CSV Parser

package main

import (
    "fmt"
    "strings"
    "strconv"
)

type Record struct {
    Name string
    Age  int
    Score float64
}

func parseCSV(line string) *Record {
    parts := strings.Split(line, ",")
    if len(parts) != 3 {
        return nil
    }
    
    age, _ := strconv.Atoi(strings.TrimSpace(parts[1]))
    score, _ := strconv.ParseFloat(strings.TrimSpace(parts[2]), 64)
    
    return &Record{
        Name:  strings.TrimSpace(parts[0]),
        Age:   age,
        Score: score,
    }
}

func main() {
    line := "Alice, 30, 95.5"
    record := parseCSV(line)
    fmt.Printf("%+v\n", record)
}

Configuration Parser

package main

import (
    "fmt"
    "strings"
    "strconv"
)

type Config struct {
    Host     string
    Port     int
    Debug    bool
    Timeout  float64
}

func parseConfig(lines []string) *Config {
    config := &Config{}
    
    for _, line := range lines {
        if strings.HasPrefix(line, "#") {
            continue
        }
        
        parts := strings.Split(line, "=")
        if len(parts) != 2 {
            continue
        }
        
        key := strings.TrimSpace(parts[0])
        value := strings.TrimSpace(parts[1])
        
        switch key {
        case "host":
            config.Host = value
        case "port":
            config.Port, _ = strconv.Atoi(value)
        case "debug":
            config.Debug, _ = strconv.ParseBool(value)
        case "timeout":
            config.Timeout, _ = strconv.ParseFloat(value, 64)
        }
    }
    
    return config
}

func main() {
    lines := []string{
        "# Configuration",
        "host=localhost",
        "port=8080",
        "debug=true",
        "timeout=30.5",
    }
    
    config := parseConfig(lines)
    fmt.Printf("%+v\n", config)
}

Best Practices

โœ… Good Practices

  1. Use fmt for formatting - Cleaner than concatenation
  2. Use strings for manipulation - Optimized functions
  3. Use strconv for conversion - Type-safe conversion
  4. Check errors - Handle conversion failures
  5. Use strings.Builder - For efficient concatenation
  6. Use raw strings - For regex and paths
  7. Document format strings - Explain complex formats
  8. Use appropriate functions - Choose the right tool

โŒ Anti-Patterns

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

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

// โŒ Bad: Ignoring conversion errors
i, _ := strconv.Atoi("not a number")

// โœ… Good: Check errors
i, err := strconv.Atoi("42")
if err != nil {
    // Handle error
}

Resources and References

Official Documentation

Tools and Resources

Summary

Essential standard library packages:

  • fmt for formatting and printing
  • strings for manipulation
  • strconv for type conversion
  • Use appropriate functions for each task
  • Check errors on conversions
  • Use strings.Builder for efficiency
  • Leverage the standard library

Master these packages for effective Go programming.

Comments