Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

fmt - 格式化 I/O

概述

fmt 包实现了格式化 I/O 功能,提供类似于 C 的 printfscanf 的函数。

包导入

import "fmt"

基本使用

// 格式化输出
fmt.Printf("Hello, %s! You are %d years old.\n", "Alice", 25)

// 打印到标准输出
fmt.Println("Hello, World!")

// 格式化字符串
s := fmt.Sprintf("Result: %v", 42)

// 格式化错误
err := fmt.Errorf("invalid value: %d", -1)

典型示例

示例 1:完整的日志输出系统

package main

import (
    "fmt"
    "os"
    "time"
)

func main() {
    // 信息日志
    fmt.Printf("[%s] INFO: Application started\n", time.Now().Format(time.RFC3339))
    
    // 警告日志
    fmt.Fprintf(os.Stderr, "[%s] WARNING: Low memory\n", time.Now().Format(time.RFC3339))
    
    // 错误日志
    err := fmt.Errorf("connection failed: %w", os.ErrNotExist)
    fmt.Fprintf(os.Stderr, "[%s] ERROR: %v\n", time.Now().Format(time.RFC3339), err)
    
    // 调试信息
    debug := true
    if debug {
        fmt.Printf("[DEBUG] Variables: %+v\n", map[string]interface{}{
            "user":   "admin",
            "role":   "superuser",
            "active": true,
        })
    }
}

运行

$ ./logger
[2024-01-01T12:00:00Z] INFO: Application started
[DEBUG] Variables: map[active:true role:superuser user:admin]

示例 2:数据报表生成器

package main

import (
    "bytes"
    "fmt"
)

func main() {
    // 生成格式化报表
    var buf bytes.Buffer
    
    // 表头
    fmt.Fprintln(&buf, "┌─────────┬────────────┬──────────┐")
    fmt.Fprintln(&buf, "│   ID    │    Name    │   Score  │")
    fmt.Fprintln(&buf, "├─────────┼────────────┼──────────┤")
    
    // 数据行
    students := []struct {
        ID    int
        Name  string
        Score float64
    }{
        {1, "Alice", 95.5},
        {2, "Bob", 87.3},
        {3, "Charlie", 92.8},
    }
    
    for _, s := range students {
        fmt.Fprintf(&buf, "│ %7d │ %-10s │ %8.2f │\n", s.ID, s.Name, s.Score)
    }
    
    // 表尾
    fmt.Fprintln(&buf, "└─────────┴────────────┴──────────┘")
    
    // 输出
    fmt.Println(buf.String())
    
    // 统计信息
    total := 0.0
    for _, s := range students {
        total += s.Score
    }
    avg := total / float64(len(students))
    fmt.Printf("\n平均分:%.2f\n", avg)
}

运行

$ ./report
┌─────────┬────────────┬──────────┐
│   ID    │    Name    │   Score  │
├─────────┼────────────┼──────────┤
│       1 │ Alice      │    95.50 │
│       2 │ Bob        │    87.30 │
│       3 │ Charlie    │    92.80 │
└─────────┴────────────┴──────────┘

平均分:91.87

一、Print 系列函数

打印带换行符

Println(a …any) (n int, err error)

说明

  • 打印参数并在末尾添加换行符
  • 参数之间用空格分隔
  • 返回写入的字节数和错误

定义/实现

func Println(a ...any) (n int, err error) {
    return Fprintln(os.Stdout, a...)
}

示例

package main

import "fmt"

func main() {
    fmt.Println("Hello")           // Hello\n
    fmt.Println("A", "B", "C")     // A B C\n
    fmt.Println(1, 2, 3)           // 1 2 3\n
    fmt.Println()                  // \n
}

打印不带换行符

Print(a …any) (n int, err error)

说明

  • 打印参数但不添加换行符
  • 参数之间用空格分隔

定义/实现

func Print(a ...any) (n int, err error) {
    return Fprint(os.Stdout, a...)
}

示例

package main

import "fmt"

func main() {
    fmt.Print("Hello")             // Hello
    fmt.Print("A", "B", "C")       // ABC
    fmt.Print(1, 2, 3)             // 123
    fmt.Print("Score: ", 95)       // Score: 95
}

二、Printf 系列函数

格式化打印

Printf(format string, a …any) (n int, err error)

说明

  • 根据格式字符串打印
  • 返回写入的字节数和错误

格式动词

  • %v - 默认格式
  • %+v - 结构体字段名
  • %#v - Go 语法格式
  • %T - 类型
  • %t - bool 的 true/false
  • %s - 字符串
  • %q - 带引号的字符串
  • %d - 十进制整数
  • %b - 二进制
  • %x - 十六进制
  • %f - 浮点数
  • %e - 科学计数法
  • %p - 指针地址

定义/实现

func Printf(format string, a ...any) (n int, err error) {
    return Fprintf(os.Stdout, format, a...)
}

示例

package main

import "fmt"

func main() {
    name := "Alice"
    age := 25
    score := 95.5
    
    // 基本格式
    fmt.Printf("Name: %s, Age: %d\n", name, age)
    
    // 浮点数格式
    fmt.Printf("Score: %f\n", score)        // 95.500000
    fmt.Printf("Score: %.2f\n", score)      // 95.50
    fmt.Printf("Score: %e\n", score)        // 9.550000e+01
    
    // 整数格式
    n := 42
    fmt.Printf("Dec: %d, Bin: %b, Hex: %x\n", n, n, n)
    
    // 结构体格式
    type Person struct {
        Name string
        Age  int
    }
    p := Person{"Bob", 30}
    fmt.Printf("%v\n", p)      // {Bob 30}
    fmt.Printf("%+v\n", p)     // {Name:Bob Age:30}
    fmt.Printf("%#v\n", p)     // main.Person{Name:"Bob", Age:30}
    
    // 类型
    fmt.Printf("Type: %T\n", p)  // main.Person
    
    // 指针
    fmt.Printf("Address: %p\n", &p)
    
    // 布尔
    fmt.Printf("True: %t, False: %t\n", true, false)
    
    // 字符串
    fmt.Printf("%s\n", "hello")      // hello
    fmt.Printf("%q\n", "hello")      // "hello"
    fmt.Printf("%x\n", "hello")      // 68656c6c6f
}

运行

$ ./program
Name: Alice, Age: 25
Score: 95.500000
Score: 95.50
Score: 9.550000e+01
Dec: 42, Bin: 101010, Hex: 2a
{Bob 30}
{Name:Bob Age:30}
main.Person{Name:"Bob", Age:30}
Type: main.Person
Address: 0xc00000a000
True: true, False: false
hello
"hello"
68656c6c6f

格式化到字符串

Sprintf(format string, a …any) string

说明

  • 根据格式字符串格式化并返回字符串
  • 不输出,只返回结果

定义/实现

func Sprintf(format string, a ...any) string {
    var buf []byte
    // ... 格式化逻辑
    return string(buf)
}

示例

package main

import (
    "fmt"
)

func main() {
    // 基本使用
    s := fmt.Sprintf("Hello, %s!", "World")
    fmt.Println(s)  // Hello, World!
    
    // 数字格式化
    price := fmt.Sprintf("$%.2f", 19.99)
    fmt.Println(price)  // $19.99
    
    // 百分比
    percent := fmt.Sprintf("%.1f%%", 75.5)
    fmt.Println(percent)  // 75.5%
    
    // 填充和对齐
    fmt.Printf("|%10s|\n", "hello")   // |     hello|
    fmt.Printf("|%-10s|\n", "hello")  // |hello     |
    fmt.Printf("|%010d|\n", 42)       // |0000000042|
    
    // 动态宽度
    width := 10
    fmt.Printf("|%*s|\n", width, "hello")  // |     hello|
}

三、Fprint 系列函数

格式化输出到 io.Writer

Fprintf(w io.Writer, format string, a …any) (n int, err error)

说明

  • 格式化输出到指定的 io.Writer
  • 返回写入的字节数和错误

定义/实现

func Fprintf(w io.Writer, format string, a ...any) (n int, err error) {
    // ... 格式化并写入
}

示例

package main

import (
    "fmt"
    "os"
    "strings"
)

func main() {
    // 输出到文件
    file, _ := os.Create("output.txt")
    fmt.Fprintf(file, "Hello, %s!\n", "File")
    file.Close()
    
    // 输出到字符串缓冲区
    var buf strings.Builder
    fmt.Fprintf(&buf, "Name: %s\n", "Alice")
    fmt.Fprintf(&buf, "Age: %d\n", 25)
    fmt.Println(buf.String())
    
    // 输出到标准错误
    fmt.Fprintf(os.Stderr, "Error: something went wrong\n")
}

打印到 io.Writer

Fprint(w io.Writer, a …any) (n int, err error)

说明

  • 打印参数到 io.Writer
  • 参数之间用空格分隔

定义/实现

func Fprint(w io.Writer, a ...any) (n int, err error) {
    // ... 打印逻辑
}

示例

package main

import (
    "fmt"
    "os"
    "strings"
)

func main() {
    // 输出到字符串
    var buf strings.Builder
    fmt.Fprint(&buf, "A", "B", "C")
    fmt.Println(buf.String())  // ABC
    
    // 输出到文件
    file, _ := os.Create("test.txt")
    fmt.Fprint(file, "Hello, File!")
    file.Close()
}

打印带换行到 io.Writer

Fprintln(w io.Writer, a …any) (n int, err error)

说明

  • 打印参数并添加换行符
  • 参数之间用空格分隔

定义/实现

func Fprintln(w io.Writer, a ...any) (n int, err error) {
    // ... 打印逻辑
}

示例

package main

import (
    "fmt"
    "os"
    "strings"
)

func main() {
    // 输出到字符串
    var buf strings.Builder
    fmt.Fprintln(&buf, "Line 1")
    fmt.Fprintln(&buf, "Line 2")
    fmt.Print(buf.String())
    
    // 输出到标准错误
    fmt.Fprintln(os.Stderr, "Error message")
}

四、Sprint 系列函数

格式化为字符串

Sprint(a …any) string

说明

  • 将参数格式化为字符串
  • 参数之间用空格分隔

定义/实现

func Sprint(a ...any) string {
    // ... 格式化逻辑
}

示例

package main

import (
    "fmt"
)

func main() {
    s := fmt.Sprint("A", "B", "C")
    fmt.Println(s)  // ABC
    
    s2 := fmt.Sprint(1, 2, 3)
    fmt.Println(s2)  // 123
    
    s3 := fmt.Sprint("Score: ", 95)
    fmt.Println(s3)  // Score: 95
}

格式化为带换行的字符串

Sprintln(a …any) string

说明

  • 格式化参数并添加换行符
  • 参数之间用空格分隔

定义/实现

func Sprintln(a ...any) string {
    // ... 格式化逻辑
}

示例

package main

import (
    "fmt"
)

func main() {
    s := fmt.Sprintln("Hello")
    fmt.Print(s)  // Hello\n
    
    s2 := fmt.Sprintln("A", "B", "C")
    fmt.Print(s2)  // A B C\n
}

五、Errorf 函数

格式化错误

Errorf(format string, a …any) error

说明

  • 根据格式字符串创建错误
  • 等价于 errors.New(Sprintf(...))

定义/实现

func Errorf(format string, a ...any) error {
    return &errorString{s: Sprintf(format, a...)}
}

示例

package main

import (
    "errors"
    "fmt"
)

func main() {
    // 基本错误
    err := fmt.Errorf("invalid value: %d", -1)
    fmt.Println(err)
    
    // 包装错误
    baseErr := errors.New("base error")
    wrappedErr := fmt.Errorf("wrapped: %w", baseErr)
    fmt.Println(wrappedErr)
    
    // 错误链
    err1 := errors.New("level 1")
    err2 := fmt.Errorf("level 2: %w", err1)
    err3 := fmt.Errorf("level 3: %w", err2)
    
    fmt.Println(err3)
    
    // 检查错误链
    if errors.Is(err3, err1) {
        fmt.Println("包含 level 1 错误")
    }
    
    // 多重包装
    err = fmt.Errorf("timeout: %w", 
        fmt.Errorf("connection: %w", 
            errors.New("failed")))
    fmt.Println(err)
}

运行

$ ./program
invalid value: -1
wrapped: base error
level 3: level 2: level 1
包含 level 1 错误
timeout: connection: failed

六、Scan 系列函数

从标准输入扫描

Scan(a …any) (n int, err error)

说明

  • 从标准输入扫描数据
  • 以空格分隔
  • 返回扫描的项目数和错误

定义/实现

func Scan(a ...any) (n int, err error) {
    return Fscan(os.Stdin, a...)
}

示例

package main

import (
    "fmt"
)

func main() {
    var name string
    var age int
    
    fmt.Print("Enter name and age: ")
    n, err := fmt.Scan(&name, &age)
    
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    
    fmt.Printf("Scanned %d items: %s, %d\n", n, name, age)
}

运行

$ ./program
Enter name and age: Alice 25
Scanned 2 items: Alice, 25

格式化扫描

Scanf(format string, a …any) (n int, err error)

说明

  • 根据格式字符串扫描
  • 返回扫描的项目数和错误

定义/实现

func Scanf(format string, a ...any) (n int, err error) {
    return Fscanf(os.Stdin, format, a...)
}

示例

package main

import (
    "fmt"
)

func main() {
    var name string
    var age int
    
    fmt.Print("Enter name and age (format: name:age): ")
    n, err := fmt.Scanf("%s:%d", &name, &age)
    
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    
    fmt.Printf("Scanned %d items: %s, %d\n", n, name, age)
}

运行

$ ./program
Enter name and age (format: name:age): Alice:25
Scanned 2 items: Alice, 25

扫描一行

Scanln(a …any) (n int, err error)

说明

  • 扫描一行数据
  • 以空格分隔,遇到换行结束

定义/实现

func Scanln(a ...any) (n int, err error) {
    return Fscanln(os.Stdin, a...)
}

示例

package main

import (
    "fmt"
)

func main() {
    var a, b, c int
    
    fmt.Print("Enter three numbers: ")
    n, err := fmt.Scanln(&a, &b, &c)
    
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    
    fmt.Printf("Scanned %d items: %d, %d, %d\n", n, a, b, c)
}

运行

$ ./program
Enter three numbers: 1 2 3
Scanned 3 items: 1, 2, 3

七、Fscan 系列函数

从 io.Reader 扫描

Fscan(r io.Reader, a …any) (n int, err error)

说明

  • 从 io.Reader 扫描数据
  • 以空格分隔

定义/实现

func Fscan(r io.Reader, a ...any) (n int, err error) {
    // ... 扫描逻辑
}

示例

package main

import (
    "fmt"
    "strings"
)

func main() {
    input := strings.NewReader("100 200 300")
    
    var a, b, c int
    n, err := fmt.Fscan(input, &a, &b, &c)
    
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    
    fmt.Printf("Scanned %d: %d, %d, %d\n", n, a, b, c)
}

格式化从 io.Reader 扫描

Fscanf(r io.Reader, format string, a …any) (n int, err error)

说明

  • 根据格式从 io.Reader 扫描

定义/实现

func Fscanf(r io.Reader, format string, a ...any) (n int, err error) {
    // ... 扫描逻辑
}

示例

package main

import (
    "fmt"
    "strings"
)

func main() {
    input := strings.NewReader("Alice:25:95.5")
    
    var name string
    var age int
    var score float64
    
    n, err := fmt.Fscanf(input, "%s:%d:%f", &name, &age, &score)
    
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    
    fmt.Printf("Scanned %d: %s, %d, %.1f\n", n, name, age, score)
}

从 io.Reader 扫描一行

Fscanln(r io.Reader, a …any) (n int, err error)

说明

  • 从 io.Reader 扫描一行
  • 遇到换行结束

定义/实现

func Fscanln(r io.Reader, a ...any) (n int, err error) {
    // ... 扫描逻辑
}

示例

package main

import (
    "fmt"
    "strings"
)

func main() {
    input := strings.NewReader("1 2 3\n4 5 6\n")
    
    var a, b, c int
    n, err := fmt.Fscanln(input, &a, &b, &c)
    
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    
    fmt.Printf("Scanned %d: %d, %d, %d\n", n, a, b, c)
}

八、Sscan 系列函数

从字符串扫描

Sscan(str string, a …any) (n int, err error)

说明

  • 从字符串扫描数据
  • 以空格分隔

定义/实现

func Sscan(str string, a ...any) (n int, err error) {
    // ... 扫描逻辑
}

示例

package main

import (
    "fmt"
)

func main() {
    input := "100 200 300"
    
    var a, b, c int
    n, err := fmt.Sscan(input, &a, &b, &c)
    
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    
    fmt.Printf("Scanned %d: %d, %d, %d\n", n, a, b, c)
}

格式化从字符串扫描

Sscanf(str string, format string, a …any) (n int, err error)

说明

  • 根据格式从字符串扫描

定义/实现

func Sscanf(str string, format string, a ...any) (n int, err error) {
    // ... 扫描逻辑
}

示例

package main

import (
    "fmt"
)

func main() {
    input := "Alice:25:95.5"
    
    var name string
    var age int
    var score float64
    
    n, err := fmt.Sscanf(input, "%s:%d:%f", &name, &age, &score)
    
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    
    fmt.Printf("Scanned %d: %s, %d, %.1f\n", n, name, age, score)
}

从字符串扫描一行

Sscanln(str string, a …any) (n int, err error)

说明

  • 从字符串扫描,遇到换行或字符串结束

定义/实现

func Sscanln(str string, a ...any) (n int, err error) {
    // ... 扫描逻辑
}

示例

package main

import (
    "fmt"
)

func main() {
    input := "1 2 3"
    
    var a, b, c int
    n, err := fmt.Sscanln(input, &a, &b, &c)
    
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    
    fmt.Printf("Scanned %d: %d, %d, %d\n", n, a, b, c)
}

九、Append 系列函数

格式化追加到切片

Appendf(b []byte, format string, a …any) []byte

说明

  • 格式化并追加到字节切片
  • 返回扩展后的切片

定义/实现

func Appendf(b []byte, format string, a ...any) []byte {
    // ... 格式化并追加
}

示例

package main

import (
    "fmt"
)

func main() {
    // 基本使用
    b := []byte("Hello, ")
    b = fmt.Appendf(b, "%s!", "World")
    fmt.Println(string(b))  // Hello, World!
    
    // 数字格式化
    b = fmt.Appendf(nil, "Score: %.2f", 95.5)
    fmt.Println(string(b))  // Score: 95.50
    
    // 多次追加
    b = []byte{}
    b = fmt.Appendf(b, "Name: %s\n", "Alice")
    b = fmt.Appendf(b, "Age: %d\n", 25)
    b = fmt.Appendf(b, "Score: %.1f\n", 95.5)
    fmt.Print(string(b))
}

运行

$ ./program
Hello, World!
Score: 95.50
Name: Alice
Age: 25
Score: 95.5

追加到切片

Append(b []byte, a …any) []byte

说明

  • 将参数追加到字节切片
  • 参数之间用空格分隔

定义/实现

func Append(b []byte, a ...any) []byte {
    // ... 追加逻辑
}

示例

package main

import (
    "fmt"
)

func main() {
    b := []byte("Data: ")
    b = fmt.Append(b, 1, 2, 3)
    fmt.Println(string(b))  // Data: 1 2 3
    
    b = fmt.Append(nil, "A", "B", "C")
    fmt.Println(string(b))  // A B C
}

追加带换行到切片

Appendln(b []byte, a …any) []byte

说明

  • 追加参数并添加换行符

定义/实现

func Appendln(b []byte, a ...any) []byte {
    // ... 追加逻辑
}

示例

package main

import (
    "fmt"
)

func main() {
    b := []byte{}
    b = fmt.Appendln(b, "Line 1")
    b = fmt.Appendln(b, "Line 2")
    b = fmt.Appendln(b, "Line 3")
    fmt.Print(string(b))
}

运行

$ ./program
Line 1
Line 2
Line 3

快速参考

格式动词

动词说明示例
%v默认格式fmt.Printf("%v", 42)
%+v结构体字段名fmt.Printf("%+v", person)
%#vGo 语法格式fmt.Printf("%#v", person)
%T类型fmt.Printf("%T", person)
%t布尔fmt.Printf("%t", true)
%s字符串fmt.Printf("%s", "hello")
%q带引号字符串fmt.Printf("%q", "hello")
%d十进制fmt.Printf("%d", 42)
%b二进制fmt.Printf("%b", 42)
%x十六进制fmt.Printf("%x", 42)
%f浮点数fmt.Printf("%f", 3.14)
%e科学计数法fmt.Printf("%e", 3.14)
%p指针地址fmt.Printf("%p", &x)
函数说明返回值
Print打印,无换行(n, err)
Println打印,有换行(n, err)
Printf格式化打印(n, err)
Fprint打印到 Writer(n, err)
Fprintln打印到 Writer+ 换行(n, err)
Fprintf格式化打印到 Writer(n, err)
Sprint格式化为字符串string
Sprintln格式化为字符串 + 换行string
Sprintf格式化字符串string

Scan 系列

函数输入源分隔符
Scan标准输入空格
Scanf标准输入格式
Scanln标准输入空格,换行结束
Fscanio.Reader空格
Fscanfio.Reader格式
Fscanlnio.Reader空格,换行结束
Sscan字符串空格
Sscanf字符串格式
Sscanln字符串空格,结束

Append 系列

函数说明
Append追加到 []byte
Appendf格式化追加到 []byte
Appendln追加 + 换行到 []byte

错误处理

函数说明
Errorf格式化创建错误

最后更新:2026-04-03
Go 版本:Go 1.23+