3.5.使用fmt包来格式化字符串
Go语言标准库中的fmt包提供了以字符串形式将数据输出到控制台、文件、其他满足io.Writer接口的值或其他字符串的打印函数,表3.3列出了这些函数。某些打印函数会返回一个错误值,当将数据打印到控制台时,通常我们会忽略该返回值,但在将数据打印到文件或网络中时,我们应始终检查该错误值。
fmt包也提供了多个扫描函数(如fmt.Scan()、fmt.Scanf()和fmt.Scanln())用于从控制台、文件或字符串中读取数据。这些函数将在第8章中使用到,参见表8.2。扫描函数的一种替代方法是使用strings. Fields()函数将每个字符串分隔为多个片段,然后使用strconv包中的函数将那些非字符串的片段转换成值类型(如数值),参见表3.8和表3.9。记得在第1章中我们通过创建一个bufio.Reader从os.Stdin中读取用户输入并通过使用bufio.Reader.ReadString()函数来读取用户输入的每一行。
最简单的输出值的方式是使用fmt.Print() 和fmt.Println()函数(打印到os.Stdout中,即控制台),或者是使用fmt.Fprint() 和fmt.Fprintf()函数来输出到给定的io.Writer中(如文件),或者是使用fmt.Sprint() 和fmt.Sprintln()函数来输出到一个字符串中。
表3.3 fmt包中的打印函数
fmt.Errorf(format, args…) | 返回一个由格式化字符串和args参数生成的错误值 |
fmt.Fprint(writer, args…) | 使用格式%v和空格分割的的非字符串将args参数写入到writer中;返回写入的字节数和一个error或nil值。 |
fmt.Fprintf(writer, format, args…) | 使用格式化字符串将args参数写入到writer中;返回写入的字节数和一个error或nil值。 |
fmt.Fprintln(writer,args…) | 使用格式%v,空格分割且以换行符结尾将args参数写入到writer中;返回写入的字节数和一个error或nil值。 |
fmt.Print(args…) | 使用格式%v和空格分割的的非字符串将args参数写入到os.Stdout中;返回写入的字节数和一个error或nil值。 |
fmt.Printf(format, args…) | 使用格式化字符串将args参数写入到os.Stdout中;返回写入的字节数和一个error或nil值。 |
fmt.Println( args…)
| 使用格式%v,空格分割且以换行符结尾将args参数写入到os.Stdout中;返回写入的字节数和一个error或nil值。 |
fmt.Sprint(args…) | 返回使用由格式%v和空格分割的的非字符串的args参数组成的字符串。 |
fmt.Sprintf(format,args…) | 返回使用由格式化字符串格式化过的args参数组成的字符串。 |
fmt.Sprintln( args…) | 返回使用由格式%v,空格分割且以换行符结尾的args参数组成的字符串。 |
表3.4 fmt包中的格式化动作
格式化动作主要用于输出单个值。如果值是一个切片,其输出通常是由方括号括起来的以空格分隔的以指定的格式化动作格式化的值的序列。如果值是一个映射,则只能使用%v 或%#v,除非其键和值是同一个类型,在这种情况下则可以使用相应的类型兼容的格式化动作。
%% | %字符常量 |
%b | 以二进制(基数为2)表示的整数值,或以科学计数法表示的以2为指数幂的浮点数 |
%c | 以Unicode编码的字符表示的整型码点值 |
%d | 以十进制(基数为10)表示的整数值 |
%e | 以科学计数法e表示的浮点数或复数值 |
%E | 以科学记数法E表示的浮点数或复数值 |
%f | 以标准数法表示的浮点数或复数值 |
%g | 使用%e或%f表示的浮点数或复数值,都会产生最紧凑输出 |
%G | 使用%E或%f表示的浮点数或复数值,都会产生最紧凑输出 |
%o | 以八进制(基数为8)表示的整数值 |
%p | 以拥有前缀0x且使用小写字母a-f(用于调试)表示的十六进制(基数为16)表示的值的地值。 |
%q | 使用Go语言语法且必要时使用转义,以双引号括起来的字符串或[]byte切片,或是以单引号括起来的数字 |
%s | 以UTF-8字节表示的字符串或[]byte切片;对于一个文本文件或一个能够显示UTF-8字节的控制台,这将会产生正确的Unicode输出 |
%t | 以true或false表示的布尔值 |
%T | 使用Go语言语法的值的类型 |
%U | 使用4位Unicode表示法表示的整型码点值;例如,fmt.Printf(“%U”, ‘¶’) 输出U+00B6 |
%v | 使用默认格式表示的内置或自定义类型的值,如果该类型存在String()方法,则输出其自定义的值 |
%x | 以十六进制(基数为16)表示的整数值,或是以十六进制数字表示的字符串或[]byte切片的值(每个字节使用两个数字表示),数字使用小写字母a-f表示 |
%X | 以十六进制(基数为16)表示的整数值,或是以十六进制数字表示的字符串或[]byte切片的值(每个字节使用两个数字表示),数字使用小写字母A-F表示 |
表3.5 fmt包中的格式化动作修饰符
space | 在负数前面输出一个“-”,在正数前面输出一个空格,或使用格式化动作%x 或%X时会在打印的字节间输出一个空格;例如,fmt.Printf(“% X”, “←”) 输出E2 86 92 |
# | 让格式化动作使用另一种输出格式: %#o输出以0开头八进制数据 %#p输出不以0x开头的指针 %#q输出以原生字符串形式(使用单引号)的字符串或[]byte切片,否则输出以双引号括起来的字符串 %#v使用Go语法将输出其自身的值 %#x输出以0x开头的十六进制 %#X输出以0X开头的十六进制 |
+ | 在数值前面输出“+”或“-”,输出字符串的ASCII字符(包含转义),输出结构体的字段名称 |
– | 值向左对齐(默认右对齐) |
0 | 让格式化动作以0而不是空格进行填充 |
n.m n .m | 对于数字,让格式化动作使用n(int类型)个字符(为避免截断可以输出更多个)和m(int类型)个小数位数输出浮点数或复数。 对于字符串,n指定了其最小宽度,如果字符串太短,那么将以空格填充,.m指定了字符串可以使用的最大字符数量(从左到右),如果字符串太长其将会被截断。M和n都可以使用*来代替,在这种情况下,可以从参数中得到它们的值。 n或.m都是可以被省略的。 |
1 2 3 4 5 | type polar struct{ radius, θ float64 } p := polar{8.32, .49} fmt.Print(-18.5, 17, "Elephant", -8+.7i, 0x3C7, '\u03C7', "a", "b", p) fmt.Println() fmt.Println(-18.5, 17, "Elephant", -8+.7i, 0x3C7, '\u03C7', "a", "b", p) |
1 2 | -18.5·17Elephant(-8+0.7i)·967·967ab{8.32·0.49} -18.5·17·Elephant·(-8+0.7i)·967·967·a·b·{8.32·0.49} |
为了清晰起见,尤其是当连续输出多个空格时,我们在显示的每个空格之间加一个浅灰色的字符(·)。
fmt.Print() 和fmt.Fprint()函数处理空白符的方式与fmt.Println() 和fmt.Fprintln() 函数略有不同。一般来说,前者对于打印单个值或对于将某个值转换成字符串且不执行错误检查(使用 strconv 包进行适当的转换)是最实用的,因为它们仅在非字符串的值之间输出空格。后者更适用于打印多个值,因为它们会在每个值之间输出空格并在末尾添加一个换行符。
在底层,这些函数使用%v格式说明符,并且它们可以不拘泥于特定的形式来打印任何内置的或自定义的值。例如,打印函数对自定义的polar类型一无所知,但仍能成功打印出polar的值。
在第6章中,我们将介绍如何为自定义类型创建一个String()方法;该方法可以以我们希望的方式输出数据。类似地,如果我们想要控制内置类型的打印行为,我们可以使用一个接受格式化字符串作为其第一个参数的打印函数。
fmt.Errorf()、fmt.Printf()、fmt.Fprintf()和frat.Sprintf()函数使用的格式化字符串由一个或多个格式化动作组成,这些格式化动作以%ML的形式表示,其中M表示一个或多个可选的格式化动作修饰符,L表示一个特定的格式化动作字符。表3.4列出了这些格式化动作。一些格式化动作接收一个或多个修饰符;表3.5中列出了这些修饰符。
我们现在将讲解一些格式化字符串的代表性例子,这样我们就可以清楚地知道它们是如何工作的。在每个例子中,我们都将给出一小段代码,然后输出其结果。