Go语言“fmt”包详解
在Go语言开发中,fmt
包是我们日常使用最频繁的标准库之一,它提供了格式化输入输出的核心功能。无论是调试时打印变量,还是接收用户输入,都离不开fmt
包的支持。
本文将重点讲解fmt
包中最常用的Println
、Printf
和Scan
系列函数,并补充其他实用函数的使用场景,帮你彻底掌握Go语言的格式化操作。
一、输出函数核心:Println与Printf的区别
在打印信息时,我们最常用的就是Println
和Printf
,但很多新手容易混淆两者的用法。下面通过对比详解它们的核心差异。
1. Println:简单输出的"快捷方式"
Println
的设计理念是"简单快速",它不需要复杂的格式控制,适合快速输出变量或常量信息。
核心特点:
- 自动在参数之间添加空格
- 自动在输出末尾添加换行符
- 无需指定格式,直接打印值的默认格式
示例代码:
package main
import "fmt"
func main() {
num := 2023
str := "Go语言"
pi := 3.14159
// 多个参数用逗号分隔
fmt.Println("数字:", num, "字符串:", str, "圆周率:", pi)
// 单个参数也会自动换行
fmt.Println("单独一行")
}
输出结果:
数字: 2023 字符串: Go语言 圆周率: 3.14159
单独一行
适用场景:快速调试、简单信息打印、不需要精确格式控制的场景。
2. Printf:精确控制格式的"格式化大师"
Printf
的核心能力是格式化输出,通过"格式化字符串"和"占位符",我们可以精确控制输出的样式,这在需要规范输出格式的场景中非常实用。
核心特点:
- 需要传入格式化字符串(包含占位符)
- 按占位符指定的格式输出后续参数
- 不会自动换行,需手动添加
\n
- 支持丰富的格式控制(如小数位数、对齐方式等)
常用占位符:
占位符 | 含义 | 示例 |
---|---|---|
%d |
十进制整数 | 100 |
%s |
字符串 | "Hello" |
%f |
浮点数 | 3.14 |
%t |
布尔值 | true /false |
%v |
自动匹配类型的默认格式 | 任意类型 |
%.2f |
保留2位小数的浮点数 | 3.14 |
%5d |
占5位宽度的整数(右对齐) | 100 (前补空格) |
示例代码:
package main
import "fmt"
func main() {
name := "小明"
age := 25
score := 95.5
// 格式化字符串中用占位符对应后续参数
fmt.Printf("姓名:%s,年龄:%d岁,成绩:%.1f分\n", name, age, score)
// 演示数字格式化
fmt.Printf("整数格式化:%5d\n", 100) // 占5位宽度
fmt.Printf("浮点数格式化:%.2f\n", 3.14159) // 保留2位小数
}
输出结果:
姓名:小明,年龄:25岁,成绩:95.5分
整数格式化: 100
浮点数格式化:3.14
适用场景:格式化日志输出、数据报表展示、需要统一格式的信息打印等。
3. Println与Printf对比总结
维度 | Println | Printf |
---|---|---|
格式控制 | 无,使用默认格式 | 通过格式化字符串精确控制 |
空格与换行 | 自动加空格和换行 | 需手动加\n ,参数间无自动空格 |
使用复杂度 | 简单,直接传参数 | 稍复杂,需掌握占位符用法 |
适用场景 | 快速调试、简单输出 | 格式规范的输出、日志等 |
二、输入函数核心:Scan系列如何读取用户输入
除了输出,fmt
包还提供了从标准输入(通常是键盘)读取数据的能力,其中Scan
和Scanln
是最常用的输入函数。
1. Scan:按空白分隔读取数据
Scan
函数会从标准输入读取数据,以空白字符(空格、制表符、换行符等)作为分隔符,将读取到的值依次存储到后续参数指定的变量中。
核心特点:
- 自动忽略输入中的空白字符(包括换行)
- 读取到足够的参数后停止(未读完的输入会保留到下一次读取)
- 变量必须传递地址(使用
&
符号),否则无法赋值
示例代码:
package main
import "fmt"
func main() {
var name string
var age int
var score float64
fmt.Println("请输入姓名、年龄、成绩(用空格分隔):")
// 传递变量地址,按顺序接收输入
n, err := fmt.Scan(&name, &age, &score)
if err != nil {
fmt.Println("输入错误:", err)
return
}
fmt.Printf("读取成功,共读取%d个值:\n", n)
fmt.Printf("姓名:%s,年龄:%d,成绩:%.1f\n", name, age, score)
}
运行效果:
请输入姓名、年龄、成绩(用空格分隔):
小明 25 95.5
读取成功,共读取3个值:
姓名:小明,年龄:25,成绩:95.5
2. Scanln:读取到换行符结束
Scanln
与Scan
的主要区别是:Scanln
在读取到换行符时会停止输入,而不会继续处理换行后的内容。
核心特点:
- 以空白字符分隔参数,但遇到换行符立即停止
- 适合读取一行完整输入的场景
- 同样需要传递变量地址
示例代码:
package main
import "fmt"
func main() {
var username string
var password string
fmt.Println("请输入用户名和密码(空格分隔后回车):")
// 读取到换行符停止,未读完的参数会导致错误
n, err := fmt.Scanln(&username, &password)
if err != nil {
fmt.Println("输入错误:", err)
return
}
fmt.Printf("用户名:%s,密码:%s\n", username, password)
}
运行效果:
请输入用户名和密码(空格分隔后回车):
admin 123456
用户名:admin,密码:123456
3. Scan使用注意事项
必须传递变量地址:
Scan
系列函数要求参数是变量的内存地址(用&
获取),如果直接传变量名会报错。输入格式必须匹配:如果输入的类型与变量类型不匹配(如给int变量输入字符串),会导致读取失败,返回错误。
空白字符的处理:
Scan
忽略所有空白(包括换行),Scanln
在换行时停止,实际开发中需根据场景选择。错误处理:始终检查
Scan
返回的错误,避免因输入异常导致程序逻辑错误。
三、其他常用“fmt”函数简介
除了上述核心函数,fmt
包还有几个高频使用的函数,我们通过场景化示例快速了解。
1. Sprintf:生成格式化字符串
Sprintf
与Printf
功能类似,但不会打印到终端,而是返回格式化后的字符串,适合需要将格式化内容作为变量使用的场景(如日志拼接、数据转换)。
示例代码:
package main
import "fmt"
func main() {
// 生成格式化字符串并赋值给变量
userInfo := fmt.Sprintf("用户[ID:%d, 姓名:%s, 年龄:%d]", 1001, "张三", 30)
// 后续可直接使用该字符串
fmt.Println("用户信息:", userInfo)
}
输出结果:
用户信息: 用户[ID:1001, 姓名:张三, 年龄:30]
2. Fprint系列:输出到文件或其他流
Fprint
、Fprintln
、Fprintf
与前面的输出函数功能类似,但它们的第一个参数是io.Writer
接口(如文件、网络连接等),用于将内容写入指定的输出流,而非标准终端。
示例:写入文件
package main
import (
"fmt"
"os"
)
func main() {
// 创建文件(实现了io.Writer接口)
file, err := os.Create("user.log")
if err != nil {
fmt.Println("创建文件失败:", err)
return
}
defer file.Close() // 确保文件最终关闭
// 写入内容到文件
fmt.Fprintln(file, "===== 用户日志 =====")
fmt.Fprintf(file, "登录用户:%s,时间:%s\n", "admin", "2025-08-06")
fmt.Fprint(file, "登录状态:成功")
}
运行后,user.log
文件内容如下:
===== 用户日志 =====
登录用户:admin,时间:2025-08-06
登录状态:成功
3. 常用函数速查表
为了方便查阅,整理fmt
包常用函数如下:
函数名 | 功能描述 | 示例 | 输出示例 |
---|---|---|---|
fmt.Print |
将一系列值输出到标准输出,值之间无分隔符,不自动换行 | fmt.Print("Hello", "World") |
HelloWorld |
fmt.Println |
将一系列值输出到标准输出,值之间用空格分隔,最后自动换行 | fmt.Println("Hello", "World") |
Hello World (换行) |
fmt.Printf |
按照格式化字符串指定的格式将值输出到标准输出 | fmt.Printf("数字: %d, 字符串: %s", 10, "Hello") |
数字: 10, 字符串: Hello |
fmt.Sprintf |
按照格式化字符串指定的格式返回一个格式化后的字符串,不进行输出 | result := fmt.Sprintf("数字: %d, 字符串: %s", 10, "Hello") fmt.Println(result) |
数字: 10, 字符串: Hello (换行) |
fmt.Fprint |
将一系列值输出到实现了io.Writer 接口的对象,值之间无分隔符,不自动换行 |
file, _ := os.Create("output.txt") fmt.Fprint(file, "Hello", "World") file.Close() |
在output.txt 文件中写入HelloWorld |
fmt.Fprintln |
将一系列值输出到实现了io.Writer 接口的对象,值之间用空格分隔,最后自动换行 |
file, _ := os.Create("output.txt") fmt.Fprintln(file, "Hello", "World") file.Close() |
在output.txt 文件中写入Hello World (换行) |
fmt.Fprintf |
按照格式化字符串指定的格式将值输出到实现了io.Writer 接口的对象 |
file, _ := os.Create("output.txt") fmt.Fprintf(file, "数字: %d, 字符串: %s", 10, "Hello") file.Close() |
在output.txt 文件中写入数字: 10, 字符串: Hello |
fmt.Scan |
从标准输入读取数据,按照空白字符(空格、制表符、换行符等)分隔输入值,并将读取的值存储到指定的变量中 | var num int fmt.Scan(&num) fmt.Println(num) 假设输入 10 ,则输出10 (换行) |
用户输入10 后,输出10 (换行) |
fmt.Scanln |
从标准输入读取数据,读取到换行符结束,并将读取的值存储到指定的变量中 | var str string fmt.Scanln(&str) fmt.Println(str) 假设输入 Hello World ,则输出Hello World (换行) |
用户输入Hello World 并回车后,输出Hello World (换行) |
fmt.Sscanf |
从字符串中按照格式化字符串指定的格式读取数据,并将读取的值存储到指定的变量中 | str := "10 Hello" var num int var s string fmt.Sscanf(str, "%d %s", &num, &s) fmt.Printf("数字: %d, 字符串: %s", num, s) |
数字: 10, 字符串: Hello |
四、总结
fmt
包是Go语言中处理输入输出的基础工具,掌握其核心函数能极大提升开发效率:
- Println 适合简单、快速的输出场景,自动处理空格和换行。
- Printf 适合需要精确格式控制的场景,通过占位符实现灵活输出。
- Scan系列 用于读取用户输入,注意传递变量地址和输入格式匹配。
- Sprintf 和 Fprint系列 扩展了格式化功能,分别用于生成字符串和写入文件/流。
建议在实际开发中多动手实践,根据具体场景选择合适的函数,避免盲目使用。
例如调试时用Println
快速输出,日志记录用Printf
规范格式,数据转换用Sprintf
生成字符串,文件写入用Fprintf
等。熟练掌握这些函数,能让你的Go代码更规范、高效!