Saturday, February 7, 2026

String Formatting

    Profile Pic of Akash AmanAkash Aman

    Updated: February 2026

    String Formatting

    Concept: String formatting in Go is primarily handled by the fmt package. It uses "verbs" (placeholders starting with %) to tell Go how to transform a variable into a string representation.

    Why: Go is strictly typed, so you cannot simply concatenate a string and an integer (e.g., "Age: " + 10). Formatting allows for type-safe, readable, and highly controlled string construction.

    The Core Functions

    FunctionOutput DestinationBehavior
    fmt.PrintfStandard OutputPrints formatted string to the console.
    fmt.SprintfReturns a StringSaves the formatted result to a variable.
    fmt.Fprintfio.WriterSends formatted text to a file, network socket, or buffer.

    The General Purpose Verbs

    Concept: These are the "Swiss Army Knives" of formatting. If you aren't sure of the specific type, or want a quick look at the data, use these.

    • %v (Value): The default format. It prints the value in a "natural" way.
    • %+v (Struct+): When printing structs, this adds the field names.
    • %#v (Go-syntax): Prints the value as it would appear in Go source code.
    • %T (Type): Prints the data type of the variable.
    go
    type User struct {
        ID   int
        Name string
    }
    
    u := User{1, "Go"}
    
    fmt.Printf("%v\n", u)  // Output: {1 Go}
    fmt.Printf("%+v\n", u) // Output: {ID:1 Name:Go}
    fmt.Printf("%#v\n", u) // Output: main.User{ID:1, Name:"Go"}
    fmt.Printf("%T\n", u)  // Output: main.User
    

    How %v Really Works

    • For Basic Types: If you have a pointer to a basic type like an int or a string, %v will indeed print the hexadecimal memory address.
    • For Structs: If you have a pointer to a struct, %v is smart. By default, it will dereference the pointer and print the struct's contents formatted inside braces.
    • For Types with a String() method: If the type (or its pointer) has a custom stringer method, %v will call that method instead of printing the address.

    Comparison Table

    Data TypeCode ExampleOutput with %v
    Pointer to Intp := new(int)0xc0000120b0 (Address)
    Pointer to Structp := &User{ID: 1}&{1} (Values)
    Pointer to Stringerp := time.Now()2026-02-07 ... (Formatted String)

    Behavioral Reason: Debugging Visibility

    • In languages like JavaScript, console.log(object) gives you a deep view. In Go, a simple %v on a pointer only gives you the memory address. Using %+v or %#v is the "Go way" to inspect the internal state of objects during development without writing custom "Stringer" methods.

    Type-Specific Verbs

    Concept: To ensure precise control over memory representation (crucial for your IoT and low-level interests), Go provides explicit verbs for different data types.

    Integers & Numbers

    • %d: Base 10 (Standard integer).
    • %b: Binary (Great for checking bitmasks or IoT sensor data).
    • %x / %X**: Hexadecimal (Used for memory addresses or color codes).
    • %f: Floating point.

    Strings & Characters

    • %s: Basic string output.
    • %q: Quoted string. Safely escapes special characters.
    • %c: Character (converts an integer/rune to its Unicode symbol).
    go
    val := 65
    
    fmt.Printf("%d\n", val) // 65
    fmt.Printf("%b\n", val) // 1000001
    fmt.Printf("%x\n", val) // 41
    fmt.Printf("%c\n", val) // A (The Unicode character for 65)
    
    path := "C:\\Users\\Go"
    fmt.Printf("%s\n", path) // C:\Users\Go
    fmt.Printf("%q\n", path) // "C:\\Users\\Go" (Includes literal quotes and escapes)
    

    Width and Precision

    Concept: You can control how much space a value takes up and how many decimal places are shown.

    • Width: %5d pads the integer to at least 5 characters wide.
    • Precision: %.2f limits a float to 2 decimal places.

    The "Right-Align" Logic

    • By default, width-padding happens on the left (right-aligning the text). To left-align (pad on the right), use a minus sign: %-5d.
    go
    pi := 3.14159
    fmt.Printf("|%8.2f|\n", pi)   // Output: |    3.14| (8 total spaces, 2 decimals)
    fmt.Printf("|%-8.2f|\n", pi)  // Output: |3.14    | (Left aligned)
    

    Formatting Performance

    Crucial: The Reflection Cost

    Behavior: Functions like Printf and Sprintf use Reflection (reflect package) internally to figure out the type of variable you passed at runtime.

    Why this matters:

    • Performance: In a high-frequency loop (like processing millions of IoT sensor packets), fmt.Sprintf is significantly slower than direct string conversion.
    • Alternative: For maximum performance, use the strconv package (e.g., strconv.Itoa(i)) which avoids reflection.
    go
    // SLOW: Uses reflection to determine 'i' is an int
    s := fmt.Sprintf("%d", 123)
    
    // FAST: Direct conversion for known types
    s := strconv.Itoa(123)
    

    Crux

    • %v is for quick development; %d/%s/%f is for intentional formatting.
    • %#v is your best friend for debugging complex structs.
    • %q is essential when logging strings that might contain hidden newlines or tabs.
    • Memory/Speed: Use fmt for readability and UI; use strconv for high-performance data processing.

    © 2026 Akash Aman | All rights reserved