Go 学习笔记(46)— Go 标准库之 fmt(输入/输出格式化参数、Printf/Fprintf/Sprintf区别、Println/Fprintln/Sprintln 区别)

1. 概述

import "fmt"

fmt 包实现了类似 C 语言 printfscanf 的格式化 I/O 。格式化动作( verb )源自 C 语言但更简单。

格式化

2. Printing 格式化

2.1 通用格式

格式化标记格式化含义
%v值的默认格式表示
%+v类似%v,但输出结构体时会添加字段名
%#v值的类型的Go语法表示
%%百分号

代码示例:

package main

import "fmt"

type Person struct {
	Name string
	Age  int
}

func main() {
	a := 10
	s := "hello world"
	p := Person{Name: "wohu", Age: 25}
	c := []int{1, 2, 3, 4}

	fmt.Printf("p %%v is %v\n", p)   // p %v is {wohu 25}
	fmt.Printf("p %%+v is %+v\n", p) // p %+v is {Name:wohu Age:25}
	fmt.Printf("p %%#v is %#v\n", p) // p %#v is main.Person{Name:"wohu", Age:25}
	fmt.Printf("p type is %T\n", p)  // p type is main.Person

	fmt.Printf("a %%#v is %#v, a type is %T\n", a, a) // a %#v is 10, a type is int
	fmt.Printf("s %%#v is %#v, s type is %T\n", s, s) // s %#v is "hello world", s type is string
	fmt.Printf("c %%v is %v, c type is %T\n", c, c)   // c %v is [1 2 3 4], c type is []int
	fmt.Printf("c %%#v is %#v, c type is %T\n", c, c) // c %#v is []int{1, 2, 3, 4}, c type is []int
}

注意当

c := []int{1, 2, 3, 4}

%v 打印的内容是 [1,2,3,4], %#v 打印的内容是 []int{1, 2, 3, 4},所以为了便于查看值类型,建议使用 %#v

2.2 布尔值格式

格式化标记格式化含义
%t单词true或false

代码示例:

func main() {
	var a bool
	fmt.Printf("a %%v is %v, %%#v is %#v, %%T is %T\n", a, a, a)
	// a %v is false, %#v is false, %T is bool
	fmt.Printf("a %%t is %t,  %%T is %T\n", a, a)
	// a %t is false,  %T is bool
	b := true
	fmt.Printf("b %%v is %v, %%#v is %#v, %%T is %T\n", b, b, b)
	// b %v is true, %#v is true, %T is bool
	fmt.Printf("b %%t is %t,  %%T is %T\n", b, b)
	// b %t is true,  %T is bool
}

2.3 整数格式

格式化标记格式化含义
%b表示为二进制
%c该值对应的unicode码值
%d表示为十进制
%o表示为八进制
%q该值对应的单引号括起来的go语法字符字面值,必要时会采用安全的转义表示
%x表示为十六进制,使用a-f
%X表示为十六进制,使用A-F
%U表示为Unicode格式:U+1234,等价于"U+%04X"

没有%u。整数如果是无符号类型自然输出也是无符号的。类似的,也没有必要指定操作数的尺寸(int8,int64)。

代码示例:

func main() {
	var i int = 15
	fmt.Printf("i %%#v is %#v\n", i) // i %#v is 15
	fmt.Printf("i %%b is %b\n", i)   // i %b is 1111
	fmt.Printf("i %%c is %c\n", i)   // i %c is 
	fmt.Printf("i %%d is %d\n", i)   // i %d is 15
	fmt.Printf("i %%o is %o\n", i)   // i %o is 17
	fmt.Printf("i %%q is %q\n", i)   // i %q is '\x0f'
	fmt.Printf("i %%x is %x\n", i)   // i %x is f
	fmt.Printf("i %%X is %X\n", i)   // i %X is F
	fmt.Printf("i %%U is %U\n", i)   // i %U is U+000F
}

2.4 浮点数与复数格式

格式化标记格式化含义
%b无小数部分、二进制指数的科学计数法,如-123456p-78;参见strconv.FormatFloat
%e科学计数法,如-1234.456e+78
%E科学计数法,如-1234.456E+78
%f有小数部分但无指数部分,如123.456
%F等价于%f
%g根据实际情况采用%e或%f格式(以获得更简洁、准确的输出)
%G根据实际情况采用%E或%F格式(以获得更简洁、准确的输出)

代码示例:

func main() {
	var i float32 = 112233445566778899
	fmt.Printf("i %%#v is %#v,  %%T is %T\n", i, i)
	//  i %#v is 1.1223345e+17,  %T is float32
	fmt.Printf("i %%b is %b\n", i) // i %b is 13065693p+33
	fmt.Printf("i %%e is %e\n", i) // i %e is 1.122334e+17
	fmt.Printf("i %%E is %E\n", i) // i %E is 1.122334E+17
	fmt.Printf("i %%f is %f\n", i) // i %f is 112233448269152256.000000
	fmt.Printf("i %%F is %F\n", i) // i %F is 112233448269152256.000000
	fmt.Printf("i %%g is %g\n", i) // i %g is 1.1223345e+17
	fmt.Printf("i %%G is %G\n", i) // i %G is 1.1223345E+17
}

2.5 字符串和[]byte 格式

格式化标记格式化含义
%s直接输出字符串或者[]byte
%q该值对应的双引号括起来的go语法字符串字面值,必要时会采用安全的转义表示
%x每个字节用两字符十六进制数表示(使用a-f)
%X每个字节用两字符十六进制数表示(使用A-F)

代码示例:

func main() {
	a := "hello"
	b := []byte(a)
	c := "你好"
	fmt.Printf("a %%s is %s, %%T is %T\n", a, a) // a %s is hello, %T is string
	fmt.Printf("b %%s is %s, %%T is %T\n", b, b) // b %s is hello, %T is []uint8
	fmt.Printf("c %%s is %s, %%T is %T\n", c, c) // c %s is 你好, %T is string
	fmt.Printf("b %%q is %q\n", b)               // b %q is "hello"
	fmt.Printf("b %%x is %x\n", b)               // b %x is 68656c6c6f
	fmt.Printf("c %%X is %X\n", c)               // c %X is E4BDA0E5A5BD
	fmt.Printf("c %%x is %x\n", c)               // c %x is e4bda0e5a5bd
}

2.6 指针格式

格式化标记格式化含义
%p表示为十六进制,并加上前导的0x

代码示例:

func main() {
	a := []int{1, 2, 3, 4}
	p := &a
	fmt.Printf("*p is %#v\n", *p)  // *p is []int{1, 2, 3, 4}
	fmt.Printf("p %%p is %p\n", p) // p %p is 0xc00000c060
}

2.7 宽度精度格式

宽度通过一个紧跟在百分号后面的十进制数指定,如果未指定宽度,则表示值时除必需之外不作填充。精度通过(可选的)宽度后跟点号后跟的十进制数指定。

  • 如果未指定精度,会使用默认精度;
  • 如果点号后没有跟数字,表示精度为 0。
格式化标记格式化含义
%f默认宽度,默认精度
%9f宽度9,默认精度
%.2f默认宽度,精度2
%9.2f宽度9,精度2
%9.f宽度9,精度0

代码示例:

import "fmt"

const PI float32 = 3.14159265358979323846

func main() {
	fmt.Printf("PI %%f is %f\n", PI)
	fmt.Printf("PI %%f is %9f\n", PI)
	fmt.Printf("PI %%f is %.3f\n", PI)
	fmt.Printf("PI %%f is %9.3f\n", PI)
	fmt.Printf("PI %%f is %9.f\n", PI)
}

输出结果:

PI %f is 3.141593
PI %f is  3.141593
PI %f is 3.142
PI %f is     3.142
PI %f is         3

宽度和精度格式化控制的是 Unicode 码值的数量(不同于 Cprintf ,它的这两个因数指的是字节的数量)。两者任一个或两个都可以使用 * 号取代,此时它们的值将被对应的参数(按’*'号和verb出现的顺序,即控制其值的参数会出现在要表示的值前面)控制,这个操作数必须是int类型。

对于大多数类型的值,宽度是输出字符数目的最小数量,如果必要会用空格填充。对于字符串,精度是输出字符数目的最大数量,如果必要会截断字符串。

对于整数,宽度和精度都设置输出总长度。采用精度时表示右对齐并用 0 填充,而宽度默认表示用空格填充。

对于浮点数,宽度设置输出总长度;精度设置小数部分长度(如果有的话),除了 %g%G ,此时精度设置总的数字个数。例如,对数字123.45,格式 %6.2f 输出123.45;格式 %.4g 输出123.5。 %e%f 的默认精度是6, %g 的默认精度是可以将该值区分出来需要的最小数字个数。

对复数,宽度和精度会分别用于实部和虚部,结果用小括号包裹。因此 %f 用于 1.2+3.4i 输出(1.200000+3.400000i)。

3. Scanning 格式化

  • ScanScanfScanln 从标准输入 os.Stdin 读取文本;
  • FscanFscanfFscanln 从指定的 io.Reader 接口读取文本;
  • SscanSscanfSscanln 从一个参数字符串读取文本;
  • ScanlnFscanlnSscanln 会在读取到换行时停止,并要求一次提供一行所有条目;
  • ScanfFscanfSscanf 只有在格式化文本末端有换行时会读取到换行为止,其他函数会将换行视为空白。

ScanfFscanfSscanf 会根据格式字符串解析参数,类似 Printf 。例如 %x 会读取一个十六进制的整数, %v 会按对应值的默认格式读取。格式规则类似 Printf ,有如下区别:

%p 未实现
%T 未实现
%e %E %f %F %g %G 效果相同,用于读取浮点数或复数类型
%s %v 用在字符串时会读取空白分隔的一个片段
flag '#''+' 未实现

4. 常用函数

4.1 func Printf

func Printf(format string, a ...interface{}) (n int, err error)

Printf 根据 format 参数生成格式化的字符串并写入标准输出。参数类型为 interface{} ,这意味着你可以传递零个或者多个任意类型参数给它,都能被正确打印。返回写入的字节数和遇到的任何错误。

4.2 func Fprintf

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

Fprintf 根据 format 参数生成格式化的字符串并写入 w 。返回写入的字节数和遇到的任何错误。

4.3 func Sprintf

func Sprintf(format string, a ...interface{}) string

Sprintf 根据 format 参数生成格式化的字符串并返回该字符串。

4.4 Printf、Fprintf、Sprintf 区别

代码示例:

func main() {
	a := "hello"
	b := "world"
	fmt.Printf("Printf is %s %s\n", a, b)
	fmt.Fprintf(os.Stdout, "Fprintf is %s+++++%s\n", a, b)
	ret := fmt.Sprintf("Sprintf is %s=====%s\n", a, b)
	fmt.Printf("ret is %s", ret)
}

输出结果:

Printf is hello world
Fprintf is hello+++++world	// 该打印是 os.Stdout 的输出,并不是 Fprintf 的输出
ret is Sprintf is hello=====world

4.5 func Print

func Print(a ...interface{}) (n int, err error)

Print 采用默认格式将其参数格式化并写入标准输出。如果两个相邻的参数都不是字符串,会在它们的输出之间添加空格。返回写入的字节数和遇到的任何错误。

4.6 func Fprint

func Fprint(w io.Writer, a ...interface{}) (n int, err error)

Fprint 采用默认格式将其参数格式化并写入 w 。如果两个相邻的参数都不是字符串,会在它们的输出之间添加空格。返回写入的字节数和遇到的任何错误。

4.7 func Sprint

func Sprint(a ...interface{}) string

Sprint 采用默认格式将其参数格式化,串联所有输出生成并返回一个字符串。如果两个相邻的参数都不是字符串,会在它们的输出之间添加空格。

4.8 Print、Fprint、Sprint 区别

代码示例:

func main() {
	a := "hello"
	b := "world"
	fmt.Print("Print: ", a, b, "\n")
	fmt.Fprint(os.Stdout, "Fprint: ", a, b, "\n")
	ret := fmt.Sprint("Sprint: ", a, b, "\n")
	fmt.Print("ret:", ret)
}

输出结果:

Print: helloworld
Fprint: helloworld	// 该打印是 os.Stdout 的输出
ret:Sprint: helloworld

4.9 func Println

func Println(a ...interface{}) (n int, err error)

Println 采用默认格式将其参数格式化并写入标准输出。总是会在相邻参数的输出之间添加空格并在输出结束后添加换行符。返回写入的字节数和遇到的任何错误。

4.10 func Fprintln

func Fprintln(w io.Writer, a ...interface{}) (n int, err error)

Fprintln 采用默认格式将其参数格式化并写入 w 。总是会在相邻参数的输出之间添加空格并在输出结束后添加换行符。返回写入的字节数和遇到的任何错误。

4.11 func Sprintln

func Sprintln(a ...interface{}) string

Sprintln 采用默认格式将其参数格式化,串联所有输出生成并返回一个字符串。总是会在相邻参数的输出之间添加空格并在输出结束后添加换行符。

4.12 Println、Fprintln、Sprintln 区别

代码示例:

func main() {
	a := "hello"
	b := "world"
	fmt.Println("Println: ", a, b)
	fmt.Fprintln(os.Stdout, "Fprintln: ", a, b)
	ret := fmt.Sprintln("Sprintln: ", a, b)
	fmt.Println("ret:", ret)
}

输出结果:

Println:  hello world
Fprintln:  hello world	// 该打印是 os.Stdout 的输出
ret: Sprintln:  hello world

4.13 func Errorf

func Errorf(format string, a ...interface{}) error

Errorf 根据 format 参数生成格式化字符串并返回一个包含该字符串的错误。

4.14 func Scanf

func Scanf(format string, a ...interface{}) (n int, err error)

Scanf 从标准输入扫描文本,根据 format 参数指定的格式将成功读取的空白分隔的值保存进成功传递给本函数的参数。返回成功扫描的条目个数和遇到的任何错误。

4.15 func Fscanf

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

Fscanfr 扫描文本,根据 format 参数指定的格式将成功读取的空白分隔的值保存进成功传递给本函数的参数。返回成功扫描的条目个数和遇到的任何错误。

4.16 func Sscanf

func Sscanf(str string, format string, a ...interface{}) (n int, err error)

Sscanf 从字符串 str 扫描文本,根据 format 参数指定的格式将成功读取的空白分隔的值保存进成功传递给本函数的参数。返回成功扫描的条目个数和遇到的任何错误。

4.17 func Scan

func Scan(a ...interface{}) (n int, err error)

Scan 从标准输入扫描文本,将成功读取的空白分隔的值保存进成功传递给本函数的参数。换行视为空白。返回成功扫描的条目个数和遇到的任何错误。如果读取的条目比提供的参数少,会返回一个错误报告原因。

4.18 func Fscan

func Fscan(r io.Reader, a ...interface{}) (n int, err error)

Fscanr 扫描文本,将成功读取的空白分隔的值保存进成功传递给本函数的参数。换行视为空白。返回成功扫描的条目个数和遇到的任何错误。如果读取的条目比提供的参数少,会返回一个错误报告原因。

4.19 func Sscan

func Sscan(str string, a ...interface{}) (n int, err error)

Sscan 从字符串 str 扫描文本,将成功读取的空白分隔的值保存进成功传递给本函数的参数。换行视为空白。返回成功扫描的条目个数和遇到的任何错误。如果读取的条目比提供的参数少,会返回一个错误报告原因。

4.20 func Scanln

func Scanln(a ...interface{}) (n int, err error)

Scanln 类似 Scan ,但会在换行时才停止扫描。最后一个条目后必须有换行或者到达结束位置。

4.21 func Fscanln

func Fscanln(r io.Reader, a ...interface{}) (n int, err error)

Fscanln 类似 Fscan ,但会在换行时才停止扫描。最后一个条目后必须有换行或者到达结束位置。

4.22 func Sscanln

func Sscanln(str string, a ...interface{}) (n int, err error)

Sscanln 类似 Sscan ,但会在换行时才停止扫描。最后一个条目后必须有换行或者到达结束位置。

参考:
https://studygolang.com/static/pkgdoc/pkg/fmt.htm

  • 2
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值