Skip to main content

Go Standard Library: fmt, strings, strconv

Created: May 8, 2026 6 min read

The fmt, strings, and strconv packages are fundamental to Go programming. This guide covers their most useful functions and patterns. For more context, see Go Installation Guide, Go Ecosystem Overview, Go Best Practices.

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.

Resources

Comments

Share this article

Scan to read on mobile