首页 / Go 语言入门教程 / 输出与格式化

Go 语言入门教程

输出与格式化

本教程共 80 篇 · 第 10 篇 · 更新于 2026-07-27 · 约 8 分钟阅读

GoGo 入门教程fmtPrintf格式化PrintlnSprintf

10. 输出与格式化

本节目标:掌握 fmt 包的各种输出函数,记住常用的格式化动词,能自由控制输出格式。

fmt 包

fmt 是 Go 标准库里最常用的包之一,负责格式化输入输出。你写的前几个程序几乎都离不开它。

import "fmt"

基本输出函数

fmt.Print

直接输出,不加换行,不加空格:

fmt.Print("Hello")
fmt.Print("World")
// 输出:HelloWorld

相邻的两个参数都不是字符串时,中间会自动加空格:

fmt.Print("a", "b")      // 输出:ab
fmt.Print(1, 2, 3)        // 输出:1 2 3
fmt.Print("a", 1, true)   // 输出:a1 true

fmt.Println

输出后自动加换行符:

fmt.Println("Hello")
fmt.Println("World")
// 输出:
// Hello
// World

多个参数之间自动加空格:

fmt.Println("Name:", "Go", "Year:", 2009)
// 输出:Name: Go Year: 2009

fmt.Printf

按格式化字符串输出,这是最灵活的方式:

fmt.Printf("我叫%s,今年%d\n", "小明", 18)
// 输出:我叫小明,今年18岁

三个函数的区别:

函数换行格式化用途
Print简单输出
Println输出一行
Printf格式化输出
Tip

Printf 不会自动加换行,需要手动写 \n。如果你想要格式化 + 自动换行,可以用 fmt.Printf\n,或者先 SprintfPrintln

格式化动词

Printf% 开头的动词(Verb)来控制输出格式。这是从 C 语言继承来的概念。

通用动词

动词含义示例
%v默认格式输出fmt.Printf("%v", 42) -> 42
%+v带字段名输出结构体fmt.Printf("%+v", user) -> {Name:Go Age:18}
%#vGo 语法表示fmt.Printf("%#v", "hi") -> "hi"
%T输出类型fmt.Printf("%T", 42) -> int
%%输出百分号fmt.Printf("100%%") -> 100%

%v 是万能的,任何类型都能用。不知道用什么的时候就用 %v

整数

动词含义示例
%d十进制fmt.Printf("%d", 42) -> 42
%b二进制fmt.Printf("%b", 10) -> 1010
%o八进制fmt.Printf("%o", 8) -> 10
%O八进制(带 0o 前缀)fmt.Printf("%O", 8) -> 0o10
%x十六进制小写fmt.Printf("%x", 255) -> ff
%X十六进制大写fmt.Printf("%X", 255) -> FF
%c对应 Unicode 字符fmt.Printf("%c", 65) -> A
%q带引号的字符fmt.Printf("%q", 65) -> 'A'

浮点数

动词含义示例
%f小数fmt.Printf("%f", 3.14) -> 3.140000
%e科学计数法(小写 e)fmt.Printf("%e", 3.14) -> 3.140000e+00
%E科学计数法(大写 E)fmt.Printf("%E", 3.14) -> 3.140000E+00
%g自动选择 %e 或 %ffmt.Printf("%g", 3.14) -> 3.14

字符串

动词含义示例
%s原样输出fmt.Printf("%s", "Go") -> Go
%q带双引号fmt.Printf("%q", "Go") -> "Go"
%x十六进制字节fmt.Printf("%x", "Go") -> 476f

布尔

动词含义示例
%t输出 true 或 falsefmt.Printf("%t", true) -> true

指针

动词含义示例
%p指针地址fmt.Printf("%p", &x) -> 0xc0000a2000

宽度和精度

% 和动词字母之间可以加数字,控制输出的宽度和精度。

宽度

fmt.Printf("|%5d|", 42)    // |   42|  右对齐,宽度5
fmt.Printf("|%-5d|", 42)   // |42   |  左对齐,宽度5
fmt.Printf("|%05d|", 42)   // |00042|  用0填充

精度

对于浮点数,小数点后的数字控制精度:

fmt.Printf("%.2f", 3.14159)  // 3.14  保留2位小数
fmt.Printf("%.4f", 3.14159)  // 3.1416  保留4位小数

对于字符串,精度控制最大长度:

fmt.Printf("%.3s", "Golang")  // Gol  只输出前3个字符

组合使用

fmt.Printf("|%8.2f|", 3.14159)  // |    3.14|  宽度8,精度2

Sprintf:格式化但不输出

fmt.SprintfPrintf 用法一样,但它不输出到屏幕,而是返回格式化后的字符串:

msg := fmt.Sprintf("你好,%s!你今年%d岁。", "小明", 18)
fmt.Println(msg)
// 输出:你好,小明!你今年18岁。

这在拼接日志、生成消息等场景非常常用。

Sprint 和 Sprintln

类似地,SprintSprintln 返回字符串而不输出:

s1 := fmt.Sprint("a", "b", "c")      // "abc"
s2 := fmt.Sprintln("a", "b", "c")    // "a b c\n"

Fprintf:输出到指定目标

fmt.Fprintf 可以输出到任何实现了 io.Writer 接口的目标:

fmt.Fprintf(os.Stdout, "输出到标准输出:%d\n", 42)
fmt.Fprintf(os.Stderr, "输出到标准错误:%d\n", 42)

这在写日志或者输出到文件时很有用。

输入函数

fmt.Scan

从标准输入读取,空格分隔:

var name string
var age int
fmt.Scan(&name, &age)
fmt.Printf("你输入了:%s, %d\n", name, age)

输入 Go 18,输出 你输入了:Go, 18

fmt.Scanf

按格式化字符串读取:

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

fmt.Scanln

读取一行,遇换行结束:

var name string
fmt.Scanln(&name)
Note

fmt.Scan 系列在简单的命令行程序里够用了。如果你要做复杂的交互式输入,建议用 bufio 包的 Scanner,处理更灵活。

实际示例

打印表格

func main() {
    fmt.Printf("%-10s %5s %5s\n", "名字", "年龄", "分数")
    fmt.Printf("%-10s %5d %5.1f\n", "小明", 18, 92.5)
    fmt.Printf("%-10s %5d %5.1f\n", "小红", 19, 88.0)
    fmt.Printf("%-10s %5d %5.1f\n", "小刚", 20, 95.3)
}

输出:

名字         年龄   分数
小明            18  92.5
小红            19  88.0
小刚            20  95.3

查看类型和值

func main() {
    x := 42
    s := "hello"
    f := 3.14

    fmt.Printf("x 的类型:%T,值:%v\n", x, x)
    fmt.Printf("s 的类型:%T,值:%v\n", s, s)
    fmt.Printf("f 的类型:%T,值:%v\n", f, f)
}

输出:

x 的类型:int,值:42
s 的类型:string,值:hello
f 的类型:float64,值:3.14
Tip

调试的时候 %T%+v 是你的好朋友。%T 看类型,%+v 看结构体内容。

常见问题

Printf 格式不匹配

fmt.Printf("%d", "hello")  // 输出:%!d(string=hello)

%d 期望整数,但你给了字符串,Go 会输出一个提示告诉你格式不对。用 go vet 可以检测这类问题。

Println 打印结构体

type User struct {
    Name string
    Age  int
}

u := User{Name: "Go", Age: 18}
fmt.Println(u)     // {Go 18}
fmt.Printf("%+v\n", u)  // {Name:Go Age:18}
fmt.Printf("%#v\n", u)  // main.User{Name:"Go", Age:18}

%+v 带字段名,%#v 带 Go 语法格式,调试时最有用。

学完这节你能做什么

  • PrintPrintlnPrintf 三种方式输出
  • 记住 %v%d%s%f%T 等常用格式化动词
  • 控制输出的宽度和精度
  • Sprintf 拼接格式化字符串
  • Scan 系列读取用户输入

下一节进入数据类型的学习,从基本类型开始。