package fmt

import "fmt"

Package fmt 实现了格式化输入输出,其函数功能类似于C语言的 printf 和 scanf。 格式化“动词”派生自C语言,但更为简洁。

输出打印

根据输出目标的不同,定义了四类打印函数。 PrintPrintlnPrintf 写入至 os.StdoutSprintSprintlnSprintf 返回一个字符串; FprintFprintlnFprintf 写入至指定的 io.WriterAppendAppendlnAppendf 将输出追加至字节切片。

每一类中的函数根据名称后缀执行格式化操作: Print、Sprint、Fprint 和 Append 对每个参数使用默认格式, 当两个操作数均非字符串时,在其间添加空格。 Println、Sprintln、Fprintln 和 Appendln 始终添加空格并追加换行符。 Printf、Sprintf、Fprintf 和 Appendf 使用一系列“动词”控制格式化规则。

格式化动词:

通用类型:

%v	使用默认格式展示值
	打印结构体时,加号标记(%+v)会输出字段名
%#v	值的Go语法表示形式
	(浮点无穷大与NaN会显示为 ±Inf 和 NaN)
%T	值的类型的Go语法表示形式
%%	字面百分号,不占用任何参数值

布尔类型:

%t	输出单词 true 或 false

整数类型:

%b	二进制表示
%c	对应Unicode码点表示的字符
%d	十进制表示
%o	八进制表示
%O	带 0o 前缀的八进制表示
%q	使用Go语法安全转义的单引号字符字面量
%x	十六进制表示,a-f 使用小写字母
%X	十六进制表示,A-F 使用大写字母
%U	Unicode格式:U+1234;等价于 "U+%04X"

浮点数与复数分量:

%b	无小数的科学计数法,指数为2的幂,
	效果等同于 strconv.FormatFloat 使用 'b' 格式,
	例如 -123456p-78
%e	科学计数法,例如 -1.234456e+78
%E	科学计数法,例如 -1.234456E+78
%f	带小数点无指数,例如 123.456
%F	%f 的同义词
%g	大指数时使用 %e,其余情况使用 %f。精度规则见下文
%G	大指数时使用 %E,其余情况使用 %F
%x	十六进制表示(指数为十进制2的幂),例如 -0x1.23abcp+20
%X	大写十六进制表示,例如 -0X1.23ABCP+20

指数始终为十进制整数。
除 %b 外,其他格式的指数至少为两位数字。

字符串与字节切片(这些动词对二者处理方式一致):

%s	字符串或切片的原始字节数据
%q	使用Go语法安全转义的双引号字符串
%x	十六进制,小写,每个字节占两个字符
%X	十六进制,大写,每个字节占两个字符

切片:

%p	第0个元素的地址,十六进制表示,带 0x 前缀

指针:

%p	十六进制表示,带 0x 前缀
%b、%d、%o、%x、%X 动词同样适用于指针,
格式化效果与整数完全一致

%v 的默认格式:

bool:                    %t
int, int8 等类型:        %d
uint, uint8 等类型:      %d,使用 %#v 时为 %#x
float32, complex64 等:   %g
string:                  %s
chan:                    %p
pointer:                 %p

对于复合对象,其元素会递归应用上述规则进行打印, 布局格式如下:

结构体:             {field0 field1 ...}
数组、切片:         [elem0 elem1 ...]
映射:               map[key1:value1 key2:value2 ...]
上述类型的指针:     &{}, &[], &map[]

宽度通过动词前的可选十进制数字指定。 若未指定,宽度为展示值所需的最小长度。 精度在(可选)宽度之后,通过句点加十进制数字指定。 无句点时使用默认精度,句点后无数字则精度为0。 示例:

%f     默认宽度,默认精度
%9f    宽度9,默认精度
%.2f   默认宽度,精度2
%9.2f  宽度9,精度2
%9.f   宽度9,精度0

宽度与精度以Unicode码点(即rune)为单位。 (这与C语言printf以字节为单位不同) 两个标记均可替换为字符 '*',其值从后续参数中获取(位于待格式化参数之前), 参数类型必须为 int。

对于大多数值,宽度为输出的最小rune数, 必要时用空格填充格式化结果。

但对于字符串、字节切片和字节数组, 精度限制待格式化输入的长度(而非输出长度), 必要时进行截断。通常以rune为单位, 但使用 %x 或 %X 格式化这些类型时,以字节为单位。

对于浮点数值,宽度设置字段最小宽度, 精度设置小数点后的位数(适用时); 例外:%g/%G 的精度设置有效数字的最大位数(移除末尾零)。 例如,数值 12.345 使用 %6.3f 打印为 12.345,%.3g 打印为 12.3。 %e、%f、%#g 的默认精度为6; %g 的默认精度为唯一标识该值所需的最少位数。

对于复数,宽度与精度独立应用于两个分量, 结果会被括号包裹,因此 %f 格式化 1.2+3.4i 会输出 (1.200000+3.400000i)。

使用 %q 格式化单个整数码点或rune切片([]rune类型)时, 无效Unicode码点会被替换为Unicode替换字符 U+FFFD, 行为与 strconv.QuoteRune 一致。

其他标记:

'+'	数值始终输出正负号;
	%q 保证仅输出ASCII字符(%+q)
'-'	右侧填充空格(左对齐字段)
'#'	备用格式:二进制加 0b 前缀(%#b)、八进制加 0 前缀(%#o)、
	十六进制加 0x/0X 前缀(%#x/%#X);%p 移除 0x 前缀(%#p);
	%q 中,若 [strconv.CanBackquote] 返回 true,输出反引号原始字符串;
	%e、%E、%f、%F、%g、%G 始终输出小数点;
	%g、%G 不移除末尾零;
	%U 中,字符可打印时输出 U+0078 'x' 格式(%#U)
' '	(空格)数值省略符号时保留占位空格(% d);
	十六进制打印字符串/切片时,字节间添加空格(% x、% X)
'0'	用前导零而非空格填充;
	数值类型中,填充位移至符号之后

不支持对应标记的动词会忽略标记。 例如无备用十进制格式,因此 %#d 与 %d 行为一致。

每个 Printf 类函数都对应一个无格式字符串的 Print 函数, 等价于对所有参数使用 %v 格式化。 另一个变体 Println 会在参数间插入空格并追加换行符。

无论使用何种动词,若参数为接口值, 将使用其内部的具体值,而非接口本身。 因此:

var i interface{} = 23
fmt.Printf("%v\n", i)

会打印 23。

除 %T 和 %p 动词外,实现了特定接口的参数会应用特殊格式化规则。 优先级顺序如下:

1. 若参数为 reflect.Value,将替换为其持有的具体值, 并按后续规则继续格式化。

2. 若参数实现 Formatter 接口,将调用该接口方法。 此时动词与标记的解析由该实现控制。

3. 若 %v 搭配 # 标记(%#v)且参数实现 GoStringer 接口, 将调用该接口方法。

当格式(Println 等函数隐式使用 %v)适用于字符串动词(%s %q %x %X), 或为 %v 且非 %#v 时,应用以下两条规则:

4. 若参数实现 error 接口,将调用 Error 方法转换为字符串, 再按动词要求格式化。

5. 若参数实现 String() string 方法,将调用该方法转换为字符串, 再按动词要求格式化。

对于切片、结构体等复合参数,格式规则递归应用于每个元素, 而非整个参数。因此 %q 会为字符串切片的每个元素加引号, %6.2f 会控制浮点数组每个元素的格式。

但使用字符串类动词(%s %q %x %X)打印字节切片时, 将其视为单个整体,与字符串处理方式一致。

避免递归场景,例如:

type X string
func (x X) String() string { return Sprintf("<%s>", x) }

递归前转换值即可解决:

func (x X) String() string { return Sprintf("<%s>", string(x)) }

自引用数据结构也可能触发无限递归, 例如切片包含自身作为元素且该类型定义了 String 方法。 此类情况极少出现,本包不做防护处理。

打印结构体时,fmt 不会也无法对未导出字段调用 Error、String 等格式化方法。

显式参数索引

PrintfSprintfFprintfAppendf 中, 默认行为是每个格式化动词依次处理调用传入的参数。 但动词前的 [n] 标记表示格式化第n个(从1开始)参数。 宽度或精度的 '*' 前使用该标记,可指定取值的参数索引。 处理完 [n] 表达式后,后续动词默认使用 n+1、n+2 等参数, 除非另行指定。

示例:

fmt.Sprintf("%[2]d %[1]d\n", 11, 22)

输出 "22 11",而:

fmt.Sprintf("%[3]*.[2]*[1]f", 12.0, 2, 6)

等价于:

fmt.Sprintf("%6.2f", 12.0)

输出 " 12.00"。由于显式索引会影响后续动词, 可通过重置首个重复参数的索引,多次打印相同值:

fmt.Sprintf("%d %d %#[1]x %#x", 16, 17)

输出 "16 17 0x10 0x11"。

格式化错误

若动词传入无效参数(例如给 %d 传字符串), 生成的字符串会包含问题描述,示例如下:

类型错误或未知动词:%!verb(type=value)
	Printf("%d", "hi"):        %!d(string=hi)
参数过多:%!(EXTRA type=value)
	Printf("hi", "guys"):      hi%!(EXTRA string=guys)
参数过少:%!verb(MISSING)
	Printf("hi%d"):            hi%!d(MISSING)
宽度/精度非整数:%!(BADWIDTH) 或 %!(BADPREC)
	Printf("%*s", 4.5, "hi"):  %!(BADWIDTH)hi
	Printf("%.*s", 4.5, "hi"): %!(BADPREC)hi
参数索引无效或使用错误:%!(BADINDEX)
	Printf("%*[2]d", 7):       %!d(BADINDEX)
	Printf("%.[2]d", 7):       %!d(BADINDEX)

所有错误均以 "%!" 开头,后接单个字符(动词), 以括号内的描述结尾。

若打印函数调用 Error 或 String 方法时触发 panic, fmt 包会重格式化 panic 错误信息, 标注其来源于 fmt 包。例如 String 方法调用 panic("bad"), 格式化结果如下:

%!s(PANIC=bad)

%!s 仅表示故障时使用的打印动词。 但若 panic 由 Error、String、GoString 方法的空接收者触发, 输出为无修饰的字符串 "<nil>"。

输入扫描

提供一组功能对等的函数,扫描格式化文本并解析为值。 ScanScanfScanlnos.Stdin 读取; FscanFscanfFscanln 从指定 io.Reader 读取; SscanSscanfSscanln 从参数字符串读取。

ScanFscanSscan 将输入中的换行符视为空格。

ScanlnFscanlnSscanln 遇到换行符时停止扫描, 要求数据项后必须跟随换行符或文件结束符EOF。

ScanfFscanfSscanf 根据格式字符串解析参数, 功能与 Printf 对等。下文所述“空格”指除换行符外的任意Unicode空白字符。

格式字符串中,% 开头的动词会读取并解析输入, 详细规则见下文。%、空格、换行符之外的字符, 必须匹配输入中的对应字符。 格式字符串中换行符前可带任意数量空格, 匹配输入中任意数量空格后接单个换行符或输入结束。 格式字符串中换行符后的空格,匹配输入中任意数量空格。 其余情况下,格式字符串中一个或多个连续空格, 匹配输入中尽可能多的空格。 除非格式字符串中的空格紧邻换行符, 否则必须匹配输入中至少一个空格或到达输入结束。

空格与换行符的处理规则区别于C语言scanf系列: C语言中换行符等同于普通空格, 且格式字符串中的空格匹配不到输入空格时不会报错。

扫描动词行为与 Printf 对等。 例如 %x 将整数解析为十六进制数, %v 解析值的默认表示格式。 未实现 Printf 的 %p、%T 动词及 #、+ 标记。 浮点与复数值支持所有有效格式化动词 (%b %e %E %f %F %g %G %x %X %v),效果一致, 支持十进制、十六进制写法(例如 "2.3e+7"、"0x4.5p-8") 及数字分隔下划线(例如 "3.14159_26535_89793")。

动词处理的输入默认以空格分隔: 除 %c 外,所有动词都会先丢弃剩余输入的前导空格; %s 动词(及 %v 读取字符串时)在首个空格或换行符处停止读取。

无格式或使用 %v 扫描整数时, 支持标准进制前缀:0b(二进制)、0o/0(八进制)、0x(十六进制), 同时支持数字分隔下划线。

宽度可作用于输入文本,但不支持精度扫描语法 (无 %5.2f,仅支持 %5f)。 指定宽度时,会在修剪前导空格后生效, 限制读取的最大rune数以满足动词要求。示例:

Sscanf(" 1234567 ", "%5s%d", &s, &i)

s 赋值为 "12345",i 赋值为 67;而:

Sscanf(" 12 34 567 ", "%5s%d", &s, &i)

s 赋值为 "12",i 赋值为 34。

所有扫描函数中,回车紧跟换行符(\r\n)视为普通换行符, 与 \n 效果一致。

所有扫描函数中,若参数实现 Scan 方法 (即实现 Scanner 接口),将调用该方法扫描文本。 此外,若扫描到的参数数量少于传入数量,返回错误。

所有待扫描参数必须为基础类型指针或 Scanner 接口实现。

ScanfFscanf 一致,Sscanf 无需消耗全部输入, 无法获取其使用的输入字符串长度。

注意:Fscan 等函数可能多读一个字符(rune), 这意味着循环调用扫描函数可能跳过部分输入。 该问题仅在输入值无空格分隔时出现。 若传入 Fscan 的读取器实现 ReadRune 方法,将使用该方法读取字符; 若同时实现 UnreadRune 方法,将保存字符避免数据丢失。 为无该能力的读取器附加这两个方法,可使用 bufio.NewReader

Example (Formats)

These examples demonstrate the basics of printing using a format string. Printf, Sprintf, and Fprintf all take a format string that specifies how to format the subsequent arguments. For example, %d (we call that a 'verb') says to print the corresponding argument, which must be an integer (or something containing an integer, such as a slice of ints) in decimal. The verb %v ('v' for 'value') always formats the argument in its default form, just how Print or Println would show it. The special verb %T ('T' for 'Type') prints the type of the argument rather than its value. The examples are not exhaustive; see the package comment for all the details.

package main

import (
	"fmt"
	"math"
	"time"
)

func main() {
	// A basic set of examples showing that %v is the default format, in this
	// case decimal for integers, which can be explicitly requested with %d;
	// the output is just what Println generates.
	integer := 23
	// Each of these prints "23" (without the quotes).
	fmt.Println(integer)
	fmt.Printf("%v\n", integer)
	fmt.Printf("%d\n", integer)

	// The special verb %T shows the type of an item rather than its value.
	fmt.Printf("%T %T\n", integer, &integer)
	// Result: int *int

	// Println(x) is the same as Printf("%v\n", x) so we will use only Printf
	// in the following examples. Each one demonstrates how to format values of
	// a particular type, such as integers or strings. We start each format
	// string with %v to show the default output and follow that with one or
	// more custom formats.

	// Booleans print as "true" or "false" with %v or %t.
	truth := true
	fmt.Printf("%v %t\n", truth, truth)
	// Result: true true

	// Integers print as decimals with %v and %d,
	// or in hex with %x, octal with %o, or binary with %b.
	answer := 42
	fmt.Printf("%v %d %x %o %b\n", answer, answer, answer, answer, answer)
	// Result: 42 42 2a 52 101010

	// Floats have multiple formats: %v and %g print a compact representation,
	// while %f prints a decimal point and %e uses exponential notation. The
	// format %6.2f used here shows how to set the width and precision to
	// control the appearance of a floating-point value. In this instance, 6 is
	// the total width of the printed text for the value (note the extra spaces
	// in the output) and 2 is the number of decimal places to show.
	pi := math.Pi
	fmt.Printf("%v %g %.2f (%6.2f) %e\n", pi, pi, pi, pi, pi)
	// Result: 3.141592653589793 3.141592653589793 3.14 (  3.14) 3.141593e+00

	// Complex numbers format as parenthesized pairs of floats, with an 'i'
	// after the imaginary part.
	point := 110.7 + 22.5i
	fmt.Printf("%v %g %.2f %.2e\n", point, point, point, point)
	// Result: (110.7+22.5i) (110.7+22.5i) (110.70+22.50i) (1.11e+02+2.25e+01i)

	// Runes are integers but when printed with %c show the character with that
	// Unicode value. The %q verb shows them as quoted characters, %U as a
	// hex Unicode code point, and %#U as both a code point and a quoted
	// printable form if the rune is printable.
	smile := '😀'
	fmt.Printf("%v %d %c %q %U %#U\n", smile, smile, smile, smile, smile, smile)
	// Result: 128512 128512 😀 '😀' U+1F600 U+1F600 '😀'

	// Strings are formatted with %v and %s as-is, with %q as quoted strings,
	// and %#q as backquoted strings.
	placeholders := `foo "bar"`
	fmt.Printf("%v %s %q %#q\n", placeholders, placeholders, placeholders, placeholders)
	// Result: foo "bar" foo "bar" "foo \"bar\"" `foo "bar"`

	// Maps formatted with %v show keys and values in their default formats.
	// The %#v form (the # is called a "flag" in this context) shows the map in
	// the Go source format. Maps are printed in a consistent order, sorted
	// by the values of the keys.
	isLegume := map[string]bool{
		"peanut":    true,
		"dachshund": false,
	}
	fmt.Printf("%v %#v\n", isLegume, isLegume)
	// Result: map[dachshund:false peanut:true] map[string]bool{"dachshund":false, "peanut":true}

	// Structs formatted with %v show field values in their default formats.
	// The %+v form shows the fields by name, while %#v formats the struct in
	// Go source format.
	person := struct {
		Name string
		Age  int
	}{"Kim", 22}
	fmt.Printf("%v %+v %#v\n", person, person, person)
	// Result: {Kim 22} {Name:Kim Age:22} struct { Name string; Age int }{Name:"Kim", Age:22}

	// The default format for a pointer shows the underlying value preceded by
	// an ampersand. The %p verb prints the pointer value in hex. We use a
	// typed nil for the argument to %p here because the value of any non-nil
	// pointer would change from run to run; run the commented-out Printf
	// call yourself to see.
	pointer := &person
	fmt.Printf("%v %p\n", pointer, (*int)(nil))
	// Result: &{Kim 22} 0x0
	// fmt.Printf("%v %p\n", pointer, pointer)
	// Result: &{Kim 22} 0x010203 // See comment above.

	// Arrays and slices are formatted by applying the format to each element.
	greats := [5]string{"Kitano", "Kobayashi", "Kurosawa", "Miyazaki", "Ozu"}
	fmt.Printf("%v %q\n", greats, greats)
	// Result: [Kitano Kobayashi Kurosawa Miyazaki Ozu] ["Kitano" "Kobayashi" "Kurosawa" "Miyazaki" "Ozu"]

	kGreats := greats[:3]
	fmt.Printf("%v %q %#v\n", kGreats, kGreats, kGreats)
	// Result: [Kitano Kobayashi Kurosawa] ["Kitano" "Kobayashi" "Kurosawa"] []string{"Kitano", "Kobayashi", "Kurosawa"}

	// Byte slices are special. Integer verbs like %d print the elements in
	// that format. The %s and %q forms treat the slice like a string. The %x
	// verb has a special form with the space flag that puts a space between
	// the bytes.
	cmd := []byte("a⌘")
	fmt.Printf("%v %d %s %q %x % x\n", cmd, cmd, cmd, cmd, cmd, cmd)
	// Result: [97 226 140 152] [97 226 140 152] a⌘ "a⌘" 61e28c98 61 e2 8c 98

	// Types that implement Stringer are printed the same as strings. Because
	// Stringers return a string, we can print them using a string-specific
	// verb such as %q.
	now := time.Unix(123456789, 0).UTC() // time.Time implements fmt.Stringer.
	fmt.Printf("%v %q\n", now, now)
	// Result: 1973-11-29 21:33:09 +0000 UTC "1973-11-29 21:33:09 +0000 UTC"

}

Output:

23
23
23
int *int
true true
42 42 2a 52 101010
3.141592653589793 3.141592653589793 3.14 (  3.14) 3.141593e+00
(110.7+22.5i) (110.7+22.5i) (110.70+22.50i) (1.11e+02+2.25e+01i)
128512 128512 😀 '😀' U+1F600 U+1F600 '😀'
foo "bar" foo "bar" "foo \"bar\"" `foo "bar"`
map[dachshund:false peanut:true] map[string]bool{"dachshund":false, "peanut":true}
{Kim 22} {Name:Kim Age:22} struct { Name string; Age int }{Name:"Kim", Age:22}
&{Kim 22} 0x0
[Kitano Kobayashi Kurosawa Miyazaki Ozu] ["Kitano" "Kobayashi" "Kurosawa" "Miyazaki" "Ozu"]
[Kitano Kobayashi Kurosawa] ["Kitano" "Kobayashi" "Kurosawa"] []string{"Kitano", "Kobayashi", "Kurosawa"}
[97 226 140 152] [97 226 140 152] a⌘ "a⌘" 61e28c98 61 e2 8c 98
1973-11-29 21:33:09 +0000 UTC "1973-11-29 21:33:09 +0000 UTC"
Example (Printers)

Print, Println, and Printf lay out their arguments differently. In this example we can compare their behaviors. Println always adds blanks between the items it prints, while Print adds blanks only between non-string arguments and Printf does exactly what it is told. Sprint, Sprintln, Sprintf, Fprint, Fprintln, and Fprintf behave the same as their corresponding Print, Println, and Printf functions shown here.

package main

import (
	"fmt"
	"math"
)

func main() {
	a, b := 3.0, 4.0
	h := math.Hypot(a, b)

	// Print inserts blanks between arguments when neither is a string.
	// It does not add a newline to the output, so we add one explicitly.
	fmt.Print("The vector (", a, b, ") has length ", h, ".\n")

	// Println always inserts spaces between its arguments,
	// so it cannot be used to produce the same output as Print in this case;
	// its output has extra spaces.
	// Also, Println always adds a newline to the output.
	fmt.Println("The vector (", a, b, ") has length", h, ".")

	// Printf provides complete control but is more complex to use.
	// It does not add a newline to the output, so we add one explicitly
	// at the end of the format specifier string.
	fmt.Printf("The vector (%g %g) has length %g.\n", a, b, h)

}

Output:

The vector (3 4) has length 5.
The vector ( 3 4 ) has length 5 .
The vector (3 4) has length 5.

Index

Examples

Functions

func Append

func Append(b []byte, a ...any) []byte

Append 使用操作数的默认格式进行格式化,将结果追加到字节切片, 并返回更新后的切片 当两个操作数均非字符串时,在操作数之间添加空格

func Appendf

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

Appendf 根据格式说明符进行格式化,将结果追加到字节切片, 并返回更新后的切片

func Appendln

func Appendln(b []byte, a ...any) []byte

Appendln 使用操作数的默认格式进行格式化,将结果追加到字节切片, 并返回更新后的切片。始终在操作数之间添加空格,并追加换行符

func Errorf

func Errorf(format string, a ...any) (err error)

Errorf 根据格式说明符格式化,并将结果字符串作为满足 error 接口的值返回。

若格式说明符包含 %w 动词且操作数为错误类型,返回的错误将实现 Unwrap 方法并返回该操作数。 若存在多个 %w 动词,返回的错误将实现 Unwrap 方法并返回 []error,其中包含所有 %w 操作数(按参数出现顺序排列)。 为 %w 动词提供未实现 error 接口的操作数是无效的。除此之外,%w 动词是 %v 的同义词。

Example

The Errorf function lets us use formatting features to create descriptive error messages.

package main

import (
	"fmt"
)

func main() {
	const name, id = "bueller", 17
	err := fmt.Errorf("user %q (id %d) not found", name, id)
	fmt.Println(err.Error())

}

Output:

user "bueller" (id 17) not found

func FormatString

func FormatString(state State, verb rune) string

FormatString 返回一个字符串,代表 State 捕获的完整格式化指令, 后跟参数动词。(State 本身不包含动词) 结果以百分号开头,后跟任意标志、宽度和精度。 未设置的标志、宽度和精度将被省略。 该函数允许 Formatter 重建触发 Format 调用的原始指令。

func Fprint

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

Fprint 使用操作数的默认格式进行格式化,并写入 w 当两个操作数均非字符串时,在操作数之间添加空格 返回写入的字节数以及遇到的任何写入错误

Example
package main

import (
	"fmt"
	"os"
)

func main() {
	const name, age = "Kim", 22
	n, err := fmt.Fprint(os.Stdout, name, " is ", age, " years old.\n")

	// The n and err return values from Fprint are
	// those returned by the underlying io.Writer.
	if err != nil {
		fmt.Fprintf(os.Stderr, "Fprint: %v\n", err)
	}
	fmt.Print(n, " bytes written.\n")

}

Output:

Kim is 22 years old.
21 bytes written.

func Fprintf

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

Fprintf 根据格式说明符进行格式化,并写入 w 返回写入的字节数以及遇到的任何写入错误

Example
package main

import (
	"fmt"
	"os"
)

func main() {
	const name, age = "Kim", 22
	n, err := fmt.Fprintf(os.Stdout, "%s is %d years old.\n", name, age)

	// The n and err return values from Fprintf are
	// those returned by the underlying io.Writer.
	if err != nil {
		fmt.Fprintf(os.Stderr, "Fprintf: %v\n", err)
	}
	fmt.Printf("%d bytes written.\n", n)

}

Output:

Kim is 22 years old.
21 bytes written.

func Fprintln

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

Fprintln 使用操作数的默认格式进行格式化,并写入 w 始终在操作数之间添加空格,并追加换行符 返回写入的字节数以及遇到的任何写入错误

Example
package main

import (
	"fmt"
	"os"
)

func main() {
	const name, age = "Kim", 22
	n, err := fmt.Fprintln(os.Stdout, name, "is", age, "years old.")

	// The n and err return values from Fprintln are
	// those returned by the underlying io.Writer.
	if err != nil {
		fmt.Fprintf(os.Stderr, "Fprintln: %v\n", err)
	}
	fmt.Println(n, "bytes written.")

}

Output:

Kim is 22 years old.
21 bytes written.

func Fscan

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

Fscan 扫描从 r 读取的文本,将连续的以空格分隔的值依次存储到各个参数中。 换行符视为空格。返回成功扫描的项数。 若该项数小于参数数量,err 将说明原因。

func Fscanf

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

Fscanf 扫描从 r 读取的文本,按照格式指定的规则将连续的以空格分隔的值 依次存储到各个参数中。返回成功解析的项数。 输入中的换行符必须与格式中的换行符匹配。

Example
package main

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

func main() {
	var (
		i int
		b bool
		s string
	)
	r := strings.NewReader("5 true gophers")
	n, err := fmt.Fscanf(r, "%d %t %s", &i, &b, &s)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Fscanf: %v\n", err)
	}
	fmt.Println(i, b, s)
	fmt.Println(n)
}

Output:

5 true gophers
3

func Fscanln

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

Fscanln 类似于 Fscan,但在换行符处停止扫描, 且最后一项之后必须为换行符或 EOF。

Example
package main

import (
	"fmt"
	"io"
	"strings"
)

func main() {
	s := `dmr 1771 1.61803398875
	ken 271828 3.14159`
	r := strings.NewReader(s)
	var a string
	var b int
	var c float64
	for {
		n, err := fmt.Fscanln(r, &a, &b, &c)
		if err == io.EOF {
			break
		}
		if err != nil {
			panic(err)
		}
		fmt.Printf("%d: %s, %d, %f\n", n, a, b, c)
	}
}

Output:

3: dmr, 1771, 1.618034
3: ken, 271828, 3.141590

func Print

func Print(a ...any) (n int, err error)

Print 使用操作数的默认格式进行格式化,并写入标准输出 当两个操作数均非字符串时,在操作数之间添加空格 返回写入的字节数以及遇到的任何写入错误

Example
package main

import (
	"fmt"
)

func main() {
	const name, age = "Kim", 22
	fmt.Print(name, " is ", age, " years old.\n")

	// It is conventional not to worry about any
	// error returned by Print.

}

Output:

Kim is 22 years old.

func Printf

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

Printf 根据格式说明符进行格式化,并写入标准输出 返回写入的字节数以及遇到的任何写入错误

Example
package main

import (
	"fmt"
)

func main() {
	const name, age = "Kim", 22
	fmt.Printf("%s is %d years old.\n", name, age)

	// It is conventional not to worry about any
	// error returned by Printf.

}

Output:

Kim is 22 years old.

func Println

func Println(a ...any) (n int, err error)

Println 使用操作数的默认格式进行格式化,并写入标准输出 始终在操作数之间添加空格,并追加换行符 返回写入的字节数以及遇到的任何写入错误

Example
package main

import (
	"fmt"
)

func main() {
	const name, age = "Kim", 22
	fmt.Println(name, "is", age, "years old.")

	// It is conventional not to worry about any
	// error returned by Println.

}

Output:

Kim is 22 years old.

func Scan

func Scan(a ...any) (n int, err error)

Scan 扫描从标准输入读取的文本,将连续的以空格分隔的值依次存储到各个参数中。 换行符视为空格。返回成功扫描的项数。 若该项数小于参数数量,err 将说明原因。

func Scanf

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

Scanf 扫描从标准输入读取的文本,按照格式指定的规则将连续的以空格分隔的值 依次存储到各个参数中。返回成功扫描的项数。 若该项数小于参数数量,err 将说明原因。 输入中的换行符必须与格式中的换行符匹配。 唯一例外:动词 %c 始终扫描输入中的下一个符文, 即使该符文是空格(或制表符等)或换行符。

func Scanln

func Scanln(a ...any) (n int, err error)

Scanln 类似于 Scan,但在换行符处停止扫描, 且最后一项之后必须为换行符或 EOF。

func Sprint

func Sprint(a ...any) string

Sprint 使用操作数的默认格式进行格式化,并返回生成的字符串 当两个操作数均非字符串时,在操作数之间添加空格

Example
package main

import (
	"fmt"
	"io"
	"os"
)

func main() {
	const name, age = "Kim", 22
	s := fmt.Sprint(name, " is ", age, " years old.\n")

	io.WriteString(os.Stdout, s) // Ignoring error for simplicity.

}

Output:

Kim is 22 years old.

func Sprintf

func Sprintf(format string, a ...any) string

Sprintf 根据格式说明符进行格式化,并返回生成的字符串

Example
package main

import (
	"fmt"
	"io"
	"os"
)

func main() {
	const name, age = "Kim", 22
	s := fmt.Sprintf("%s is %d years old.\n", name, age)

	io.WriteString(os.Stdout, s) // Ignoring error for simplicity.

}

Output:

Kim is 22 years old.

func Sprintln

func Sprintln(a ...any) string

Sprintln 使用操作数的默认格式进行格式化,并返回生成的字符串 始终在操作数之间添加空格,并追加换行符

Example
package main

import (
	"fmt"
	"io"
	"os"
)

func main() {
	const name, age = "Kim", 22
	s := fmt.Sprintln(name, "is", age, "years old.")

	io.WriteString(os.Stdout, s) // Ignoring error for simplicity.

}

Output:

Kim is 22 years old.

func Sscan

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

Sscan 扫描参数字符串,将连续的以空格分隔的值依次存储到各个参数中。 换行符视为空格。返回成功扫描的项数。 若该项数小于参数数量,err 将说明原因。

func Sscanf

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

Sscanf 扫描参数字符串,按照格式指定的规则将连续的以空格分隔的值 依次存储到各个参数中。返回成功解析的项数。 输入中的换行符必须与格式中的换行符匹配。

Example
package main

import (
	"fmt"
)

func main() {
	var name string
	var age int
	n, err := fmt.Sscanf("Kim is 22 years old", "%s is %d years old", &name, &age)
	if err != nil {
		panic(err)
	}
	fmt.Printf("%d: %s, %d\n", n, name, age)

}

Output:

2: Kim, 22

func Sscanln

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

Sscanln 类似于 Sscan,但在换行符处停止扫描, 且最后一项之后必须为换行符或 EOF。

Types

type Formatter

type Formatter interface {
	Format(f State, verb rune)
}

Formatter 由任何实现了 Format 方法的值实现。 该实现控制如何解释 State 和 rune, 并可调用 SprintFprint 等方法生成输出。

type GoStringer

type GoStringer interface {
	GoString() string
}

GoStringer 由任何实现了 GoString 方法的值实现, 该方法定义了该值的 Go 语法格式。 当值作为操作数传递给 %#v 格式时,会调用 GoString 方法进行打印。

Example
package main

import (
	"fmt"
)

// Address has a City, State and a Country.
type Address struct {
	City    string
	State   string
	Country string
}

// Person has a Name, Age and Address.
type Person struct {
	Name string
	Age  uint
	Addr *Address
}

// GoString makes Person satisfy the GoStringer interface.
// The return value is valid Go code that can be used to reproduce the Person struct.
func (p Person) GoString() string {
	if p.Addr != nil {
		return fmt.Sprintf("Person{Name: %q, Age: %d, Addr: &Address{City: %q, State: %q, Country: %q}}", p.Name, int(p.Age), p.Addr.City, p.Addr.State, p.Addr.Country)
	}
	return fmt.Sprintf("Person{Name: %q, Age: %d}", p.Name, int(p.Age))
}

func main() {
	p1 := Person{
		Name: "Warren",
		Age:  31,
		Addr: &Address{
			City:    "Denver",
			State:   "CO",
			Country: "U.S.A.",
		},
	}
	// If GoString() wasn't implemented, the output of `fmt.Printf("%#v", p1)` would be similar to
	// Person{Name:"Warren", Age:0x1f, Addr:(*main.Address)(0x10448240)}
	fmt.Printf("%#v\n", p1)

	p2 := Person{
		Name: "Theia",
		Age:  4,
	}
	// If GoString() wasn't implemented, the output of `fmt.Printf("%#v", p2)` would be similar to
	// Person{Name:"Theia", Age:0x4, Addr:(*main.Address)(nil)}
	fmt.Printf("%#v\n", p2)

}

Output:

Person{Name: "Warren", Age: 31, Addr: &Address{City: "Denver", State: "CO", Country: "U.S.A."}}
Person{Name: "Theia", Age: 4}

type ScanState

type ScanState interface {
	// ReadRune 从输入中读取下一个符文(Unicode 码点)。
	// 若在 Scanln、Fscanln 或 Sscanln 期间调用,ReadRune() 在返回第一个 '\n' 后
	// 或读取超出指定宽度时,将返回 EOF。
	ReadRune() (r rune, size int, err error)
	// UnreadRune 使下一次调用 ReadRune 时返回同一个符文。
	UnreadRune() error
	// SkipSpace 跳过输入中的空白字符。换行符会根据当前执行的操作做适配处理;
	// 更多信息参见包文档。
	SkipSpace()
	// Token 若 skipSpace 为 true 则跳过输入中的空白字符,随后返回满足 f(c) 条件的
	// Unicode 码点序列。若 f 为 nil,则使用 !unicode.IsSpace(c),即令牌将包含非空白字符。
	// 换行符会根据当前执行的操作做适配处理;更多信息参见包文档。
	// 返回的切片指向共享数据,该数据可能在下次调用 Token、使用该 ScanState 作为输入调用 Scan 函数
	// 或调用方的 Scan 方法返回时被覆盖。
	Token(skipSpace bool, f func(rune) bool) (token []byte, err error)
	// Width 返回宽度选项的值以及该选项是否已设置。
	// 单位为 Unicode 码点。
	Width() (wid int, ok bool)
	// 由于 ReadRune 由该接口实现,扫描例程永远不应调用 Read,
	// 且 ScanState 的有效实现可选择始终从 Read 返回错误。
	Read(buf []byte) (n int, err error)
}

ScanState 表示传递给自定义扫描器的扫描状态。 扫描器可以逐符文扫描,也可以请求 ScanState 获取下一个以空格分隔的令牌。

type Scanner

type Scanner interface {
	Scan(state ScanState, verb rune) error
}

Scanner 由任何实现了 Scan 方法的值实现,该方法扫描输入中值的表示形式 并将结果存储到接收者中,接收者必须为指针才能生效。 对于实现了该接口的 ScanScanfScanln 参数,都会调用其 Scan 方法。

type State

type State interface {
	// Write 是用于输出待打印格式化内容的函数。
	Write(b []byte) (n int, err error)
	// Width 返回宽度选项的值以及该选项是否已设置。
	Width() (wid int, ok bool)
	// Precision 返回精度选项的值以及该选项是否已设置。
	Precision() (prec int, ok bool)

	// Flag 报告字符标志 c 是否已设置。
	Flag(c int) bool
}

State 表示传递给自定义格式化器的打印器状态。 它提供对 io.Writer 接口的访问,以及操作数格式说明符的标志和选项信息。

type Stringer

type Stringer interface {
	String() string
}

Stringer 由任何实现了 String 方法的值实现, 该方法定义了该值的“原生”格式。 当值作为操作数传递给接受字符串的格式, 或传递给 Print 这类无格式打印器时,会调用 String 方法进行打印。

Example
package main

import (
	"fmt"
)

// Animal has a Name and an Age to represent an animal.
type Animal struct {
	Name string
	Age  uint
}

// String makes Animal satisfy the Stringer interface.
func (a Animal) String() string {
	return fmt.Sprintf("%v (%d)", a.Name, a.Age)
}

func main() {
	a := Animal{
		Name: "Gopher",
		Age:  2,
	}
	fmt.Println(a)
}

Output:

Gopher (2)