fmt包使用总结
Posted 黄河大道东
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了fmt包使用总结相关的知识,希望对你有一定的参考价值。
fmt包中实现了格式化的I/O函数(类似C语言中的printf和scanf,但更加简单)。
一般格式化输出规则
fmt.Println
对于复杂类型,默认按以下规则打印:
struct
: field0 field1 …array, slice
: [elem0 elem1 …]maps
: map[key1:value1 key2:value2 …]pointer to above
: &, &[], &map[]
通用格式化字符串规则
fmt.Printf
%v
:值的默认格式,变量的自然形式(natural format);%+v
:当打印结构体时,输出结构体成员名与值;%#v
:当打印结构体时,输出结构体类型名、成员名与值%T
:打印类型(相应值的类型);%%
:打印百分号;
type ListNode struct
Val int
Next *ListNode
tmp := ListNode
Val: -1,
Next: nil,
fmt.Printf(" %v \\n %+v \\n %#v \\n %T \\n", tmp, tmp, tmp, tmp)
// 依次输出
// -1 <nil>
// Val:-1 Next:<nil>
// ListNodeVal:-1, Next:(*ListNode)(nil)
// ListNode
指针
地址格式化符:
%p
:打印指针的地址(以0x开始);对于切片打印首个元素的地址;
sl := []int1,2,3
fmt.Printf(" %v \\n %+v \\n %#v \\n %p \\n", sl, sl, sl, sl)
// [1 2 3]
// [1 2 3]
// []int1, 2, 3
// 0xc00000c3a0
数值
布尔类型:
%t
:打印true 或 false
整数:
%b
:二进制表示%c
:相应Unicode码点所表示的字符%d
:十进制表示%o
:八进制表示%q
:单引号围绕的字符字面值%x
:十六进制表示,字母形式为小写 a-f%X
:十六进制表示,字母形式为大写 A-F%U
:Unicode格式:U+1234,等同于 “U+%04X”
浮点与复数:
%b
:指数为2的幂的科学计数法,与 strconv.FormatFloat中的 ‘b’ 转换格式一致。例如 -123456p-78%e
:科学计数法,例如 -1234.456e+78%E
:科学计数法,例如 -1234.456E+78%f
:有小数点而无指数,例如 123.456%g
:根据情况选择 %e 或 %f 以产生更紧凑的(无末尾的0)输出%G
:根据情况选择 %E 或 %f 以产生更紧凑的(无末尾的0)输出
字符串与字节序列
字符串与byte切片:
%s
:字符串或切片的无解译字节;%q
:双引号围绕的字符串;%x
:十六进制,小写字母,每字节两个字符;%X
:十六进制,大写字母,每字节两个字符;
s := "字符"
fmt.Printf("%v, %q, %s, %x, %x", s, s, s, s, s)
// 字符, "字符", 字符, e5ad97e7aca6, e5 ad 97 e7 ac a6
sl := []byte65, 74, 77
fmt.Printf("%v, %q, %s, %X, %X", sl, sl, sl, sl, sl)
// [65 74 77], "AJM", AJM, 414A4D, 41 4A 4D
宽度与精度
-
宽度:通过百分号后面的十进制数指定;若未指定宽度,表示除必需之外不作填充;
-
精度(可能有):宽度后跟点号后跟的十进制数指定;若未指定精度,则使用默认精度;如果点号后没有跟数字,表示精度为0。
-
%f
:默认宽度,默认精度 -
%9f
:宽度9, 默认精度 -
%.2f
:默认宽度, 精度2 -
%9.2f
宽度9, 精度2 -
%9.f
宽度9, 精度0
标识符
标识符与填充符号:
-
+
: 总是输出数值的正负号;对%q(%+q)会生成全部是ASCII字符的输出(通过转义); -
-
: 在输出右边填充空白而不是默认的左边(即从默认的右对齐切换为左对齐); -
#
: 切换格式;- 八进制数前加0(%#o)
- 十六进制数前加0x(%#x)或0X(%#X),指针去掉前面的0x(%#p);
- 对%q(%#q),如果strconv.CanBackquote返回真会输出反引号括起来的未转义字符串;
- 对%U(%#U),如果字符是可打印的,会在输出Unicode格式、空格、单引号括起来的go字面值;
-
(空格)
: 对于数值,正数前加空格而负数前加负号;对于字符串采用%x或%X时(% x或% X)会给各打印的字节之间加空格; -
0
: 使用0而不是空格填充,对于数值类型会把填充的0放在正负号后面;
占位符
go支持显示参数占位符,通过在输出格式中指定其输出的顺序即可;参数从1开始,使用中括号括起来。
宽度与精度中的*
可通过后面参数替换。
fmt.Printf("%[2]d, %[1]d", 11, 22) // 22, 11
fmt.Sprintf("%[3]*.[2]*[1]f", 12.0, 2, 6) // 等价于:fmt.Sprintf("%6.2f", 12.0)
格式化错误
所有格式化错误(如将一个字符串提供给%d),都会输出一个以“%!”开始的错误信息,后跟错误内容。
var i int = 1
fmt.Printf("%s", i) // %!s(int=1)
GoStringer & Stringer
Stringer
接口包含String()
方法;任何类型只要定义了String()
方法,就相当于定制了输出(类似C#等中的toString);通过print
直接输出或%v
输出时,就调用此定制输出:
type Stringer interface
String() string
而GoStringer
接口包含了GoString()
方法,用于定制%#v
的格式化输出:
type GoStringer interface
GoString() string
例如:
type Animal struct
Name string
Age uint
func (a Animal) String() string
return fmt.Sprintf("Stringer: %v (%d)", a.Name, a.Age)
func (a Animal) GoString() string
return fmt.Sprintf("GoStringer: %v (%d)", a.Name, a.Age)
func TestFormat()
a := AnimalName: "Gopher",Age: 2,
fmt.Printf("%v, %#v", a, a) // Stringer: Gopher (2), GoStringer: Gopher (2)
fmt.Println(a) // Stringer: Gopher (2)
// 若不定制(即不实现String与GoString),则输出会如下
// Gopher 2, format.AnimalName:"Gopher", Age:0x2
// Gopher 2
Scanning
一组读取格式化文本获取值的函数:
Scan、Scanf、Scanln从标准输入os.Stdin中读取;
Fscan、Fscanf、Fscanln从指定的io.Reader中读取;
Sscan、Sscanf、Sscanln从字符串中读取。
Scanln、Fscanln、Sscanln在读取到换行时停止,并要求一次提供一行所有条目;
Scanf、Fscanf、Sscanf只有在格式化文本末端有换行时会读取到换行为止,其它函数则将换行符视为空格;
Scanf、Fscanf、Sscanf会根据格式字符串解析参数,类似Printf。
要定制自定义格式化输入的类型需要实现Scanner接口:
// Scanner 由自定义类型实现,用于实现该类型的自定义扫描过程。
// 当扫描器需要解析该类型的数据时,会调用其 Scan 方法。
type Scanner interface
// state 用于获取占位符中的宽度信息,也用于从扫描器中读取数据进行解析。
// verb 是占位符中的动词
Scan(state ScanState, verb rune) error
// 由扫描器(Scan 之类的函数)实现,用于给自定义扫描过程提供数据和信息。
type ScanState interface
// ReadRune 从扫描器中读取一个字符,如果用在 Scanln 类的扫描器中,
// 则该方法会在读到第一个换行符之后或读到指定宽度之后返回 EOF。
// 返回“读取的字符”和“字符编码所占用的字节数”
ReadRune() (r rune, size int, err error)
// UnreadRune 撤消最后一次的 ReadRune 操作,
// 使下次的 ReadRune 操作得到与前一次 ReadRune 相同的结果。
UnreadRune() error
// SkipSpace 为 Scan 方法提供跳过开头空白的能力。
// 根据扫描器的不同(Scan 或 Scanln)决定是否跳过换行符。
SkipSpace()
// Token 用于从扫描器中读取符合要求的字符串,
// Token 从扫描器中读取连续的符合 f(c) 的字符 c,准备解析。
// 如果 f 为 nil,则使用 !unicode.IsSpace(c) 代替 f(c)。
// skipSpace:是否跳过开头的连续空白。返回读取到的数据。
// 注意:token 指向共享的数据,下次的 Token 操作可能会覆盖本次的结果。
Token(skipSpace bool, f func(rune) bool) (token []byte, err error)
// Width 返回占位符中的宽度值以及宽度值是否被设置
Width() (wid int, ok bool)
// 因为上面实现了 ReadRune 方法,所以 Read 方法永远不应该被调用。
// 一个好的 ScanState 应该让 Read 直接返回相应的错误信息。
Read(buf []byte) (n int, err error)
Printing
一组格式化输出的函数:
- Print、Println和Printf:将各参数格式化到标准输出os.Stdout;
- Fprint、Fprintln和Fprintf:将各参数格式化到io.Writere中;
- Sprint、Sprintln和Sprintf:将各参数格式化到字符串;
- 要定制自定义格式化输出的类型需要实现Formatter接口:
// Formatter 由自定义类型实现,用于实现该类型的自定义格式化过程。
// 当格式化器需要格式化该类型的变量时,会调用其 Format 方法。
type Formatter interface
// f 用于获取占位符的旗标、宽度、精度等信息,也用于输出格式化的结果
// c 是占位符中的动词
Format(f State, c rune)
// 由格式化器(Print 之类的函数)实现,用于给自定义格式化过程提供信息
type State interface
// Formatter 通过 Write 方法将格式化结果写入格式化器中,以便输出。
Write(b []byte) (ret int, err error)
// Formatter 通过 Width 方法获取占位符中的宽度信息及其是否被设置。
Width() (wid int, ok bool)
// Formatter 通过 Precision 方法获取占位符中的精度信息及其是否被设置。
Precision() (prec int, ok bool)
// Formatter 通过 Flag 方法获取占位符中的旗标[+- 0#]是否被设置。
Flag(c int) bool
Errorf
go中的返回错误都通过error
来表示,errors.New
和fmt.Errorf
函数用于创建实现error
接口的错误对象:
type error interface
Error() string
Errorf
功能与Sprintf
类似,但将格式化结果字符串包装成error
返回,以方便生成所需的error
错误类型。
func Dived(i int, j int) (r int, err error)
if j == 0
err = fmt.Errorf("param-2 can not %d", j)
return
return i / j, err
以上是关于fmt包使用总结的主要内容,如果未能解决你的问题,请参考以下文章