格式化输出 (fmt)
fmt 包提供了格式化 I/O 功能,是 Go 语言中最常用的包之一。
📋 学习目标
- 掌握 fmt 包的基本用法
- 理解格式化占位符
- 学会格式化输出和输入
- 了解 fmt 包的高级功能
🎯 基本输出
Print 系列函数
go
package main
import "fmt"
func main() {
// Print: 直接输出,不换行
fmt.Print("Hello")
fmt.Print("World")
// 输出: HelloWorld
// Println: 输出后换行
fmt.Println("Hello")
fmt.Println("World")
// 输出:
// Hello
// World
// Printf: 格式化输出
fmt.Printf("姓名: %s, 年龄: %d\n", "张三", 30)
// 输出: 姓名: 张三, 年龄: 30
}🔤 格式化占位符
通用占位符
go
%v // 默认格式
%+v // 打印结构体时包含字段名
%#v // Go 语法表示
%T // 类型
%% // 字面量 %布尔值
go
%t // true 或 false整数
go
%b // 二进制
%o // 八进制
%d // 十进制
%x // 十六进制(小写)
%X // 十六进制(大写)
%c // Unicode 字符
%U // Unicode 格式浮点数
go
%e // 科学计数法(小写)
%E // 科学计数法(大写)
%f // 十进制表示
%g // 自动选择 %e 或 %f
%G // 自动选择 %E 或 %f字符串和字节切片
go
%s // 字符串
%q // 带引号的字符串
%x // 十六进制(小写)
%X // 十六进制(大写)指针
go
%p // 指针地址(十六进制)💻 代码示例
基本格式化
go
package main
import "fmt"
func main() {
name := "张三"
age := 30
height := 175.5
// 基本格式化
fmt.Printf("姓名: %s\n", name)
fmt.Printf("年龄: %d\n", age)
fmt.Printf("身高: %.1f cm\n", height)
// 使用 %v(默认格式)
fmt.Printf("信息: %v\n", name)
fmt.Printf("信息: %+v\n", name)
fmt.Printf("信息: %#v\n", name)
fmt.Printf("类型: %T\n", name)
}宽度和精度
go
package main
import "fmt"
func main() {
num := 123
// 宽度
fmt.Printf("|%5d|\n", num) // | 123|
fmt.Printf("|%-5d|\n", num) // |123 |
fmt.Printf("|%05d|\n", num) // |00123|
// 浮点数精度
pi := 3.14159
fmt.Printf("%.2f\n", pi) // 3.14
fmt.Printf("%.4f\n", pi) // 3.1416
}结构体格式化
go
package main
import "fmt"
type Person struct {
Name string
Age int
}
func main() {
p := Person{Name: "张三", Age: 30}
fmt.Printf("%v\n", p) // {张三 30}
fmt.Printf("%+v\n", p) // {Name:张三 Age:30}
fmt.Printf("%#v\n", p) // main.Person{Name:"张三", Age:30}
}📥 输入函数
Scan 系列函数
go
package main
import "fmt"
func main() {
var name string
var age int
// Scan: 从标准输入读取
fmt.Print("请输入姓名和年龄: ")
fmt.Scan(&name, &age)
fmt.Printf("姓名: %s, 年龄: %d\n", name, age)
// Scanf: 格式化输入
fmt.Print("请输入姓名: ")
fmt.Scanf("%s", &name)
fmt.Printf("姓名: %s\n", name)
// Scanln: 读取一行
fmt.Print("请输入一行文本: ")
var line string
fmt.Scanln(&line)
fmt.Printf("输入: %s\n", line)
}📥 输入函数
Scan 系列函数
Scan 系列函数从标准输入读取数据:
go
package main
import "fmt"
func main() {
var name string
var age int
var married bool
// Scan: 从标准输入扫描,由空白符分隔
fmt.Scan(&name, &age, &married)
fmt.Printf("扫描结果: name=%s age=%d married=%t\n", name, age, married)
// Scanf: 按照指定格式读取
fmt.Scanf("name:%s age:%d married:%t", &name, &age, &married)
fmt.Printf("格式化扫描结果: name=%s age=%d married=%t\n", name, age, married)
// Scanln: 遇到换行时停止
fmt.Scanln(&name, &age, &married)
fmt.Printf("Scanln结果: name=%s age=%d married=%t\n", name, age, married)
}Sprint 系列函数
Sprint 系列函数生成字符串而不输出:
go
package main
import "fmt"
func main() {
hello := "hello"
world := "world"
// Sprint: 拼接字符串
s1 := fmt.Sprint("测试 Sprint", " ", hello, " ", world)
// Sprintf: 格式化拼接
name := "枯藤"
age := 18
s2 := fmt.Sprintf("name:%s,age:%d", name, age)
// Sprintln: 拼接并添加换行符
s3 := fmt.Sprintln("枯藤")
fmt.Println(s1, s2, s3)
}🔧 高级功能
Sprintf - 格式化字符串
go
package main
import "fmt"
func main() {
name := "张三"
age := 30
// 格式化但不输出,返回字符串
message := fmt.Sprintf("姓名: %s, 年龄: %d", name, age)
fmt.Println(message)
}Fprintf - 格式化写入
go
package main
import (
"fmt"
"os"
)
func main() {
// 写入到文件
file, _ := os.Create("output.txt")
defer file.Close()
fmt.Fprintf(file, "姓名: %s, 年龄: %d\n", "张三", 30)
}Errorf - 格式化错误
go
package main
import (
"fmt"
"errors"
)
func divide(a, b float64) error {
if b == 0 {
return fmt.Errorf("除数不能为零: %.2f / %.2f", a, b)
}
return nil
}
func main() {
err := divide(10, 0)
if err != nil {
fmt.Println(err)
}
}🏃♂️ 实践练习
练习 1: 格式化输出表格
使用 fmt 包输出一个格式化的表格。
练习 2: 输入验证
编写一个程序,从用户输入读取数据并进行验证。
练习 3: 日志格式化
使用 fmt 包格式化日志输出。
🤔 思考题
- Print、Println、Printf 有什么区别?
- 什么时候使用 Sprintf?
- 如何控制浮点数的精度?
- 格式化占位符的宽度和精度如何设置?
📚 扩展阅读
⏭️ 下一章节
时间处理 (time) → 学习 Go 语言的时间操作
💡 提示: fmt 包是 Go 语言中最常用的包之一,熟练掌握格式化占位符可以让你更高效地处理输出!
