# Understanding the fmt Package in GO

The fmt package is one of the most fundamental and frequently used packages in Go. Whether you’re printing values, formatting strings, scanning input, or even wrapping errors — fmt is everywhere.

Because of its importance, the fmt package is also a common topic in Go interviews, especially around formatting verbs, stringers, and error wrapping.

In this article, we’ll explore:

* What the fmt package does
    
* Printing functions
    
* Formatting verbs
    
* Creating formatted strings
    
* Scanning input
    
* Working with writers (`Fprint`, `Fprintln`, `Fprintf`)
    
* Error wrapping using `fmt.Errorf`
    
* Implementing the `fmt.Stringer` interface
    
* Width, padding & precision
    
* Struct, slice & map formatting
    
* A complete example
    

This article is ideal for beginners, intermediate developers, and anyone preparing for Go interviews.

## What Is the fmt Package?

The `fmt` package provides a set of functions for:

* Formatted output (printing)
    
* Formatted input (scanning)
    
* Working with strings
    
* Working with I/O streams
    
* Error creation & wrapping
    

Import it using:

```go
import "fmt"
```

Let’s explore everything in detail.

## Printing in Go using fmt

### `fmt.Println()` — Print with newline

```go
fmt.Println("Hello", "World")
```

Output

```bash
Hello World
```

### `fmt.Print()` — Print without newline

```go
fmt.Print("Hello ")
fmt.Print("World")
```

### `fmt.Printf()` — Formatted output

Uses formatting verbs like `%s`, `%d`, `%v`, etc.

```go
name := "Rohit"
age := 24

fmt.Printf("My name is %s and I am %d year old\n", name,age)
```

## Important `fmt` Format Verbs

**General Verbs**

| Verb | Meaning |
| --- | --- |
| %v | Default format |
| %+v | Shows struct field names |
| %#v | Go-syntax representation |
| %T | Prints the type |

Example:

```go
type User struct {
    Name string
    Age int
}

u := User{"Rohit",24}

fmt.Printf("%v\n",u) // Default format
fmt.Printf("%+v/n",u) // Show struct field names
fmt.Printf("%#v\n",u) // Go-syntax representation
fmt.Printf("%T\n",u) // Prints the type
```

**String Verbs**

| Verb | Meaning |
| --- | --- |
| %s | String |
| %q | Quoted string |
| %x | Hex format |

Number verbs

| Verb | Meaning |
| --- | --- |
| %d | Integer |
| %f | Float |
| %b | Binary |
| %t | Boolean |

## Building Strings Instead of Printing

Use the `Sprintf` family when you want to create a string instead of printing it.

### fmt.Sprintf

```go
msg := fmt.Sprintf("Hi %s, score: %d","Rohit",90)
fmt.Println(msg)
```

## Writing to Files, Buffers & HTTP Responses — `Fprint`, `Fprintf`, `Fprintln`

These functions write to any `io.Writer`, not just stdout.

Example: Writing to a file

```go
file,_ := os.Create("outout.txt")
fmt.Fprintf(file,"Hello %s!", "Rohit")
```

This is widely used in

* Web servers (http.ResponseWriter)
    
* Logging systems
    
* Buffers
    
* Files
    

## Reading Input — Scan ScanIn, Scanf

### fmt.Scan — space-separated input

```go
var name string
var age int
fmt.Scan(&name,&age)
```

### fmt.ScanIn (stops at newline)

```go
var city string
fmt.Scanln(&city)
```

### fmt.Scanf (formatted input)

```go
var name string
var age int
fmt.Scanf("%s %d",&name,&age)
```

## Error Handling with fmt.Errorf

### creating errors

```go
err := fmt.Errorf("invalid input")
```

### Wrapping errors using `%w`

```go
err := fmt.Errorf("db error: %w", originalErr)
```

Then unwrap

```go
errors.Is(err,originalErr)
```

I have explained this error handling in detail in this article → [https://blog.rohitlokhande.in/error-handling-in-go](https://blog.rohitlokhande.in/error-handling-in-go)

## Implementing fmt.Stringer — Customize Struct Printing

`fmt.Stringer` is an interface

```plaintext
type Stringer interface {
    String() string
}
```

Implement it on your struct:

```go
type User struct {
    Name string
    Age int
}

func (u User) String() string {
    return fmt.Sprintf("User(Name=%s, Age=%d)",u.Name, u.Age)
}
func main() {
    u := User{"Rohit", 24}
    fmt.Println(u)
}
```

```go
User(Name=Rohit, Age=24)
```

## Formatting Width, Alignment,Padding & Precision

### Width

```go
fmt.Printf("|%10s|\n", "Go") // right-aligned
fmt.Printf("|%-10s|\n","Go") // left-aligned
```

### Zero-padding

```go
fmt.Printf("%05d\n",42) // 00042
```

### Floating precision

```go
fmt.Printf("%.2f\n",3.14159) // 3.14
```

## Formatting Structs, Maps, Slices

```go
user := map[string]string{"name":"Rohit"}
fmt.Printf("Map:%+v\n",user)
```

Output

```bash
Map:map[name:Rohit]
```

## Using fmt With Buffers (io.Writer)

### What is Buffer?

A buffer is a temporary storage area in memory used to hold data before it is processed, written, or read.

Think of a buffer like a bucket.

* You collect some data in the bucket (buffer).
    
* Once enough data is collected or when ready, you pour it out (write it somewhere).
    
* This avoids sending small pieces one by one.
    

Buffers help make input/output operations faster and more efficient.

### Why Do We Need Buffers?

Because reading or writing small amounts of data very frequently is slow.

Example:

* Writing to a file every time you add a character will slow down the process.
    
* Instead, write to a buffer in memory and then flush it to a file in larger chunks. This speeds up the process.
    

```go
import (
    "fmt";
    "bytes"
 )
var b bytes.Buffer
fmt.Fprintln(&b,"Hello Buffer")
fmt.Println("Buffer content:",b.String())
```

We have covered the basic concepts of the fmt package, which are widely used. There are also some less common but useful concepts that we will explore further.

## `fmt.GoStringer` Interface

`fmt.GoStringer` is an interface similar to `fmt.Stringer`, but it is used when formatting a type using:

* `%#v` (Go-syntax representation)
    
* `fmt.GoString()`
    

Interface definition:

```go
type GoStringer interface {
    GoString() string
}
```

If your type implements `GoString()` string, then `%#v` will call your custom method.

Example:

```go
package main

import (
    "fmt"
)

type User struct {
    Name string
    Age  int
}

// Implementing GoStringer
func (u User) GoString() string {
    return fmt.Sprintf("User{Name: %q, Age: %d}", u.Name, u.Age)
}

func main() {
    u := User{"Rohit", 24}

    fmt.Println("Normal print:")
    fmt.Println(u) // does NOT use GoString

    fmt.Println("\nGo-syntax print using %#v:")
    fmt.Printf("%#v\n", u) // uses GoString()
}
```

Output

```bash
Normal print:
{Rohit 24}

Go-syntax print using %#v:
User{Name: "Rohit", Age: 24}
```

### What happening here?

`fmt.Println(u)` → Uses the default structure formatting because we did not implement Stringer.

`fmt.Printf("%#v", u)` → Now Go sees that User implements the `GoString() string` method, so it prints the custom Go-like struct representation.

### Why do we need GoString?

fmt.Stringer is for human-readable output.

fmt.GoStringer is for debugging, logging, and developer-friendly Go syntax output.

## fmt.Appendf, Append, Appendln

These functions were added to Go to make it easier to append formatted data to a byte slice without using a `bytes.Buffer` or `strings.Builder`.

That means instead of

```go
b := []byte{}
b = append(b,fmt.Sprintf("Hello %s",name))
```

You can directly do:

```go
b = fmt.Appendf(b, "Hello %s", name)
```

### `fmt.Append`

* Similar to `fmt.Sprint`.
    
* Converts arguments to string form.
    
* Appends to a byte slice,
    
* No formatting verbs required.
    

Example

```go
package main
import (
    "fmt"
)

func main(){
    b := []byte("Start: ")
    b = fmt.Append(b,"Hello"," ",124)
    fmt.Println(string(b))
}
```

Output

```bash
Start: Hello 123
```

### `fmt.Appendln`

* Similar to `fmt.Sprintln`.
    
* Appends arguments with spaces and a newline
    

Example

```go
package main
import "fmt"

func main() {
    b := []byte{}
    b = fmt.Appendln(b,"Hello","world")
    b = fmt.Appendln(b,10, 20, 30)
    fmt.Println(string(b))
}
```

Output

```bash
Hello World
10 20 30
```

### `fmt.Appendf`

* Similar to `fmt.Sprintf`
    
* You can use formatting verbs (`%d`,`%s`,`%v` etc)
    

Example

```go
package main

import "fmt"

func main() {
	b := []byte("User: ")

	b = fmt.Appendf(b, "%s (%d years old)", "Rohit", 25)

	fmt.Println(string(b))
}
```

Output

```bash
User: Rohit (25 years old)
```

### When to Use Append Functions?

These functions are useful when:

* You want zero allocation or minimal memory overhead.
    
* You want a lightweight alternative to `bytes.Buffer`.
    
* You want to efficiently build output in a byte slice.
    
* High-performance systems (servers, loggers, serializers).
    

## FAQ: Frequently Asked Questions About Go’s fmt Package

1. **What is the fmt package used for in Go?**
    
    The fmt package is used for formatted I/O operations such as printing to the console, formatting strings, scanning input, and writing to buffers or byte slices. It provides functions like `Println`, `Printf`, `Sprintf`, `Scan`, and more.
    
2. **What is the difference between** `Print`**,** `Println`**, and** `Printf`**?**
    

| Function | Behavior |
| --- | --- |
| Print | Prints values without newline or formatting |
| Println | Prints values separated by spaces + automatically adds newline |
| Printf | Prints formatted output using verbs like `%s`, `%d`, `%v` |

3. **What are formatting verbs in fmt?**
    
    Formatting verbs are special placeholders (e.g., %d, %s, %v) used to format data.
    
    Example:
    
    * %s → string
        
    * %d → integer
        
    * %f → float
        
    * %v → value in default format
        
    
4. **What is** `fmt.Stringer` **and why is it important**
    
    `fmt.Stringer` is an interface with the method → `String() string`.  
    If a type implements this method, fmt uses it to decide how that type should be printed.  
    This is very helpful in debugging and logging.
    
5. **What is** `fmt.GoStringer`**?**
    
    `fmt.GoStringer` is an interface for generating Go-syntax-friendly output.
    
    It uses the `GoString() string` interface.
    
    This result is used when formatting with `%#v`.
    
6. **What’s the difference between bus := bytes.Buffer{} and using fmt functions?**
    

| Approach | Best Use Case |
| --- | --- |
| bytes.Buffer | High-Performace string building, especially in loops |
| fmt.Sprint / fmt.Sprintf | Readable formatting, convenient, but more allocations |
| fmt.Append\* functions | Fast, allocation-free appending to byte slices. |

7. **What are fmt.Append, Appendf, and Appendln ?**
    
    These functions append formatted data directly to a byte slice.
    
    * Append → like Sprint
        
    * Appendln → like Sprintln
        
    * Appendf → like Sprintf
        
    
    They are faster and avoid extra allocations, making them useful in logging or serialization.
    
8. **Is fmt package slow compared other manual string concatenation?**
    
    fmt is extremely optimised, but
    
    * It is slower than direct concatenation (+)
        
    * It is slower than strings.Builder
        
    * It is slower than bytes.Buffer
        
    
    However, it providers:
    
    * cleaner code
        
    * safe formatting
        
    * powerful formatting verbs
        
    
    For performance-critical sections, avoid using fmt in tight loops.
    
9. **What happens if formatting verbs don’t match the data type?**
    
    fmt does not crash, unlike other languages. Instead, it prints a fallback format.
    
    Example:
    
    ```go
    fmt.Printf("%d","hello")
    ```
    
    ```bash
    %!d(string=hello)
    ```
    

10. **Can fmt print coloured output?**
    
    No. fmt does not support ANSI colors. Use third-party libraries such as
    
    * [github.com/fatih/color](http://github.com/fatih/color)
        
    * [github.com/mgutz/ansi](http://github.com/mgutz/ansi)
        
11. **Why should I implement String() for custom structs?**
    
    Because:
    
    * Your logs become cleaner
        
    * Your debugging becomes easier
        
    * fmt.Printf(“%v“) output readable data
        

## Conclusion

The fmt package is one of the first tools every Go developer learns—and for good reason. It simplifies printing, formatting, scanning, and working with different data types. From basic functions like Println to advanced features like Stringer, formatting verbs, and the new Append functions, fmt makes everyday coding much easier and more readable.

If you understand how fmt works, you can write cleaner logs, better debug your programs, and format data more effectively. It’s a small package, but it plays a big role in every Go project.
