Go
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Functions and Methods
-
Section 4: Concurrency
-
Section 5: Packages and Tooling
-
Section 6: More Standard Library
-
Section 7: Building Services
-
Section 8: Advanced Go
-
Section 9: Go in the Cloud-Native Ecosystem
-
Section 10: Data Structures and Algorithms in Go
-
Section 11: Testing and Deployment
-
Section 12: Practical Projects
-
Section 13: More Standard Library Practice
-
Section 14: More Practice Projects
-
Section 15: Design Patterns in Go
-
Section 16: Interview Practice
-
Section 17: Package fmt In Depth
-
Section 18: Package strings and strconv
-
Section 19: Package os and io
-
Section 20: Package time
-
Section 21: Package sort and container
-
Section 22: Package encoding
-
Section 23: Package net/http In Depth
-
Section 24: Package context
-
Section 25: Package regexp and bytes
-
Section 26: Package errors In Depth
-
Section 27: Package crypto and hash
-
Section 28: Package flag and log
-
Section 29: Package sync In Depth
-
Section 30: More Practice Exercises
-
Section 31: Go Modules and Workspaces In Depth
-
Section 32: Generics Deep Dive (Go 1.18+)
-
Section 33: Testing Package In Depth
-
Section 34: More Interview and Whiteboard Practice
-
Section 35: Package math and unicode
-
Section 36: Package path and filepath
-
Section 37: Package database/sql
-
Section 38: Package text/template and html/template
-
Section 39: Package archive and compress
-
Section 40: Lower-Level net Package
-
Section 41: Package runtime and reflect
-
Section 42: Package embed and io/fs
-
Section 43: Go Assembly and CGO Basics
-
Section 44: Building CLIs and TUIs
-
Section 45: Go Performance Tuning
-
Section 46: More Real-World Projects
-
Section 47: Go in Production
-
Section 48: Go Design Patterns
-
Section 49: Go Interfaces Deep Dive
-
Section 50: Final Practice and Review
107: Println, Printf, and Sprintf Family
When you're first starting out with Go, your instinct is probably to treat strings the way you do in JavaScript or Python—just smashing things together with the + operator. It feels natural. You have a variable, you have a label, and you want them to appear on the same line. But once you start dealing with mixed types, like integers or floats, that approach falls apart fast.
The Concatenation Headache
Imagine you're building a small CLI tool to report the status of a server. You've got a server name, an uptime count in seconds, and a CPU load percentage. If you do this the naive way, your code ends up looking like a cluttered mess of type conversions:
name := "production-web-01"
uptime := 86400
cpuLoad := 12.5
fmt.Println("Server: " + name + " | Uptime: " + strconv.Itoa(uptime) + "s | Load: " + fmt.Sprintf("%.2f", cpuLoad) + "%")
I've seen this in plenty of junior PRs. It's tedious to write and even harder to read. You're constantly jumping between strconv.Itoa for integers and fighting with fmt.Sprintf just to get a decimal point right, all while managing a dozen quotation marks and plus signs. It's brittle; if you want to change the order of the fields, you have to surgically rearrange the entire string concatenation chain.
Letting Printf Do the Heavy Lifting
This is where fmt.Printf becomes your best friend. Instead of building a string piece by piece, you define a template and then plug your variables into it. It separates the "what the output looks like" from "what the data is."
fmt.Printf("Server: %s | Uptime: %ds | Load: %.2f%%\n", name, uptime, cpuLoad)
Notice how much cleaner that is. We use "verbs" like %s for strings, %d for integers, and %.2f to tell Go we want a float with exactly two decimal places. I personally find this much more maintainable because if my boss tells me the uptime needs to be in hours instead of seconds, I just change the variable and the template without worrying about breaking the surrounding string glue. Just remember that Printf doesn't add a newline automatically—you have to add that \n at the end yourself, or your next print statement will be glued to the end of this one.
Choosing Between Println and Sprintf
Now, you might be wondering why we even have Println or Sprintf if Printf is so powerful. It comes down to intent and destination.
Use fmt.Println when you're just debugging or dumping data. It's the "quick and dirty" option. It automatically adds spaces between arguments and puts a newline at the end. I use it mostly for logging something simple to the console where I don't care about the exact formatting.
But here is the crucial part: Printf and Println send their output directly to the standard output (your terminal). What happens if you need that formatted string to actually do something? Maybe you need to send it as an email body, save it to a database, or return it as part of an error message. That's where fmt.Sprintf comes in.
// This doesn't print anything to the screen.
// It returns a string that we can store in a variable.
statusMessage := fmt.Sprintf("Alert: Server %s is overloading at %.2f%%", name, cpuLoad)
if cpuLoad > 90.0 {
sendAlertEmail(statusMessage)
}
Think of Sprintf as "String Print Format." It uses the exact same verb system as Printf, but instead of shouting the result into the void of the console, it hands the result back to you as a usable string variable. If you find yourself using + to build a string that you're then passing into another function, you should almost certainly be using Sprintf instead.
📋 Practical Task
Build a Bank Transaction Receipt Formatter
You need to create a program that formats a bank transaction into a clean, human-readable receipt. Instead of just printing the values, you must use a combination of the fmt family to handle different requirements.
Requirements:
- Create three variables:
accountHolder(string),amount(float64), andtransactionID(int). - Use
fmt.Sprintfto create a formatted string calledreceiptHeaderthat looks like:"Account: [Name] | ID: [ID]". - Use
fmt.Printfto print a line showing the amount, ensuring it is formatted to exactly two decimal places with a currency symbol (e.g.,"Amount: $125.50"). - Use
fmt.Printlnto print a final footer message:"Thank you for banking with us!".
Your output should look similar to this:
Account: Jane Doe | ID: 98765
Amount: $1250.75
Thank you for banking with us!There are no comments for now.