package fmt
import "fmt"
fmt包实现了类似C语言printf和scanf的格式化I/O。格式化动作('verb')源自C语言但更简单。
Printing
verb:
通用:
%v 值的默认格式表示
package main
import "fmt"
func main() {
//%v 值的默认格式表示
var a int
a = 100
var b bool
b = true
var c string
c = "golang"
var d float64
d = 3.141592
fmt.Printf("a:%v--b:%v--c:%v--d:%v",a,b,c,d)
}
输出:
a:100--b:true--c:golang--d:3.141592
%+v 类似%v,但输出结构体时会添加字段名
package main
import "fmt"
func main() {
//%+v 类似%v,但输出结构体时会添加字段名
type Person struct {
Name string
Age int
}
var p Person
p.Name = "老王"
p.Age = 28
fmt.Printf("%v\n",p)
fmt.Printf("%+v",p)
}
输出:
{老王 28}
{Name:老王 Age:28}
%#v 值的Go语法表示
package main
import "fmt"
func main() {
//%#v 值的Go语法表示
var name string
name = "老李"
fmt.Printf("%v\n",name)
fmt.Printf("%#v\n",name)
}
输出:
老李
"老李"
%T 值的类型的Go语法表示
package main
import "fmt"
func main() {
//%T 值的类型的Go语法表示
name := "老张"
age := 38
fmt.Printf("name值的类型是:%T\nage值的类型是:%T",name,age)
}
输出:
name值的类型是:string
age值的类型是:int
%% 百分号
package main
import "fmt"
func main() {
//%% 百分号
classroom := "初一年二班"
fmt.Printf("%v,及格人数占班级总人数的78%",classroom)
fmt.Println("")
fmt.Printf("%v,及格人数占班级总人数的78%%",classroom)
}
输出:
初一年二班,及格人数占班级总人数的78%!(NOVERB)
初一年二班,及格人数占班级总人数的78%
布尔值:
%t 单词true或false
package main
import "fmt"
func main() {
//%t 单词true或false
var b bool
b = 1>2
fmt.Printf("b的值是:%t",b)
}
输出:
b的值是:false
整数:
%b 表示为二进制
%d 表示为十进制
%o 表示为八进制
%x 表示为十六进制,使用a-f
%X 表示为十六进制,使用A-F
package main
import "fmt"
func main() {
//%b 表示为二进制
//%d 表示为十进制
//%o 表示为八进制
//%x 表示为十六进制,使用a-f
//%X 表示为十六进制,使用A-F
var num int
num = 95
fmt.Printf("num的值是:%v,表示为二进制时候是:%b\n",num,num)
fmt.Printf("num的值是:%v,表示为十进制时候是:%d\n",num,num)
fmt.Printf("num的值是:%v,表示为八进制时候是:%o\n",num,num)
fmt.Printf("num的值是:%v,表示为十六进制,使用a-f时候是:%x\n",num,num)
fmt.Printf("num的值是:%v,表示为十六进制,使用A-F时候是:%X\n",num,num)
}
输出:
num的值是:95,表示为二进制时候是:1011111
num的值是:95,表示为十进制时候是:95
num的值是:95,表示为八进制时候是:137
num的值是:95,表示为十六进制,使用a-f时候是:5f
num的值是:95,表示为十六进制,使用A-F时候是:5F
%q 该值对应的单引号括起来的go语法字符字面值,必要时会采用安全的转义表示
package main
import "fmt"
func main() {
//%q 该值对应的单引号括起来的go语法字符字面值,必要时会采用安全的转义表示
var str = `我是中国人,"我有中国心"`
fmt.Printf("%q",str)
}
输出:
"我是中国人,\"我有中国心\""
浮点数与复数的两个组分:
%b 无小数部分、二进制指数的科学计数法,如-123456p-78;参见strconv.FormatFloat
package main
import "fmt"
func main() {
//%b 无小数部分、二进制指数的科学计数法,如-123456p-78;参见strconv.FormatFloat
var flo float64
flo = 3.1415926
fmt.Printf("%b",flo)
}
输出:
7074237631354954p-51
%e 科学计数法,如-1234.456e+78
%E 科学计数法,如-1234.456E+78
package main
import "fmt"
func main() {
//%e 科学计数法,如-1234.456e+78
//%E 科学计数法,如-1234.456E+78
a := 1234.5678
fmt.Printf("%e\n",a)
fmt.Printf("%E\n",a)
}
输出:
1.234568e+03
1.234568E+03
%f 有小数部分但无指数部分,如123.456
%F 等价于%f
package main
import "fmt"
func main() {
//%f 有小数部分但无指数部分,如123.456
//%F 等价于%f
a := 1.234568e+03
fmt.Printf("%f\n",a)
fmt.Printf("%F\n",a)
}
输出:
1234.568000
1234.568000
%g 根据实际情况采用%e或%f格式(以获得更简洁、准确的输出)
%G 根据实际情况采用%E或%F格式(以获得更简洁、准确的输出)
字符串和[]byte:
%s 直接输出字符串或者[]byte
package main
import "fmt"
func main() {
//%s 直接输出字符串或者[]byte
var str = "golang"
fmt.Printf("%s\n",str)
fmt.Printf("%v",str)
}
输出:
golang
golang
指针:
%p 表示为十六进制,并加上前导的0x
package main
import "fmt"
func main() {
//%p 表示为十六进制指针,并加上前导的0x
var a = 1
var p = &a
fmt.Println(p)
fmt.Printf("%p",p)
}
输出:
0xc000012088 //数值每台电脑都不一样
0xc000012088 //数值每台电脑都不一样
宽度通过一个紧跟在百分号后面的十进制数指定,如果未指定宽度,则表示值时除必需之外不作填充。精度通过(可选的)宽度后跟点号后跟的十进制数指定。如果未指定精度,会使用默认精度;如果点号后没有跟数字,表示精度为0。举例如下:
%f: 默认宽度,默认精度
%9f 宽度9,默认精度
%.2f 默认宽度,精度2
%9.2f 宽度9,精度2
%9.f 宽度9,精度0
package main
import "fmt"
func main() {
//浮点数的精度
var f = 1234.12345
//%f: 默认宽度,默认精度
fmt.Printf("%f\n",f)
fmt.Printf("%f.\n",f)
//%9f 宽度9,默认精度
fmt.Printf("%9f\n",f)
//%.2f 默认宽度,精度2
fmt.Printf("%.2f\n",f)
//%9.2f 宽度9,精度2
fmt.Printf("%9.2f\n",f)
//%9.f 宽度9,精度0
fmt.Printf("%9.f\n",f)
}
输出:
1234.123450
1234.123450.
1234.123450
1234.12
1234.12
1234
type Stringer
type Stringer interface {String() [string](#string)}
实现了Stringer接口的类型(即有String方法),定义了该类型值的原始显示。当采用任何接受字符的verb(%v %s %q %x %X)动作格式化一个操作数时,或者被不使用格式字符串如Print函数打印操作数时,会调用String方法来生成输出的文本。
type GoStringer
type GoStringer interface {GoString() [string](#string)}
实现了GoStringer接口的类型(即有GoString方法),定义了该类型值的go语法表示。当采用verb %#v格式化一个操作数时,会调用GoString方法来生成输出的文本。
type State
type State interface {
// Write方法用来写入格式化的文本
Write(b [][byte](#byte)) (ret [int](#int), err [error](#error))
// Width返回宽度值,及其是否被设置
Width() (wid [int](#int), ok [bool](#bool))
// Precision返回精度值,及其是否被设置
Precision() (prec [int](#int), ok [bool](#bool))
// Flag报告是否设置了flag c(一个字符,如+、-、#等)
Flag(c [int](#int)) [bool](#bool)
}
State代表一个传递给自定义Formatter接口的Format方法的打印环境。它实现了io.Writer接口用来写入格式化的文本,还提供了该操作数的格式字符串指定的选项和宽度、精度信息(通过调用方法)。
type Formatter
type Formatter interface {
// c为verb,f提供verb的细节信息和Write方法用于写入生成的格式化文本
Format(f [State](#State), c [rune](#rune))
}
实现了Formatter接口的类型可以定制自己的格式化输出。Format方法的实现内部可以调用Sprint或Fprint等函数来生成自身的输出。
type ScanState
type ScanState interface {
// 从输入读取下一个rune(Unicode码值),在读取超过指定宽度时会返回EOF
// 如果在Scanln、Fscanln或Sscanln中被调用,本方法会在返回第一个'\n'后再次调用时返回EOF
ReadRune() (r [rune](#rune), size [int](#int), err [error](#error))
// UnreadRune方法让下一次调用ReadRune时返回上一次返回的rune且不移动读取位置
UnreadRune() [error](#error)
// SkipSpace方法跳过输入中的空白,换行被视为空白
// 在Scanln、Fscanln或Sscanln中被调用时,换行被视为EOF
SkipSpace()
// 方法从输入中依次读取rune并用f测试,直到f返回假;将读取的rune组织为一个[]byte切片返回。
// 如果skipSpace参数为真,本方法会先跳过输入中的空白。
// 如果f为nil,会使用!unicode.IsSpace(c);就是说返回值token将为一串非空字符。
// 换行被视为空白,在Scanln、Fscanln或Sscanln中被调用时,换行被视为EOF。
// 返回的切片指向一个共享内存,可能被下一次调用Token方法时重写;
// 或被使用该Scanstate的另一个Scan函数重写;或者在本次调用的Scan方法返回时重写。
Token(skipSpace [bool](#bool), f func([rune](#rune)) [bool](#bool)) (token [][byte](#byte), err [error](#error))
// Width返回返回宽度值,及其是否被设置。单位是unicode码值。
Width() (wid [int](#int), ok [bool](#bool))
// 因为本接口实现了ReadRune方法,Read方法永远不应被在Scanner接口中使用。
// 一个合法的ScanStat接口实现可能会选择让本方法总是返回错误。
Read(buf [][byte](#byte)) (n [int](#int), err [error](#error))
}
ScanState代表一个将传递给Scanner接口的Scan方法的扫描环境。 Scan函数中,可以进行一次一个rune的扫描,或者使用Token方法获得下一个token(比如空白分隔的token)。
type Scanner
type Scanner interface {
Scan(state [ScanState](#ScanState), verb [rune](#rune)) [error](#error)
}
当Scan、Scanf、Scanln或类似函数接受实现了Scanner接口的类型(其Scan方法的receiver必须是指针,该方法从输入读取该类型值的字符串表示并将结果写入receiver)作为参数时,会调用其Scan方法进行定制的扫描。
func Printf
func Printf(format [string](#string), a ...interface{}) (n [int](#int), err [error](#error))
Printf根据format参数生成格式化的字符串并写入标准输出。返回写入的字节数和遇到的任何错误。
package main
import "fmt"
func main() {
//Printf根据format参数生成格式化的字符串并写入标准输出。返回写入的字节数和遇到的任何错误。
var str = "我是一条龙"
//golang中一个汉字占三个字节,换行符也占一个字节。
num,err := fmt.Printf("%v\n\n",str)
fmt.Println(num,err)
}
输出:
我是一条龙
17 <nil>
func Fprintf
func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error)
Fprintf根据format参数生成格式化的字符串并写入w。返回写入的字节数和遇到的任何错误。
package main
import (
"fmt"
"os"
)
func main() {
a := "hello"
b := "world"
fmt.Fprintf(os.Stdout, "%s %s\n", a,b)
}
输出:
hello world
func Sprintf
func Sprintf(format string, a ...interface{}) string
Sprintf根据format参数生成格式化的字符串并返回该字符串。
package main
import (
"fmt"
)
func main() {
a := "hello"
b := "world"
ab := fmt.Sprintf("%v %v",a,b)
fmt.Println(ab)
}
输出:
hello world
func Print
func Print(a ...interface{}) (n [int](#int), err [error](#error))
Print采用默认格式将其参数格式化并写入标准输出。如果两个相邻的参数都不是字符串,会在它们的输出之间添加空格。返回写入的字节数和遇到的任何错误。
func Fprint
func Fprint(w [io](https://studygolang.com/static/pkgdoc/pkg/io.htm).[Writer](#Writer), a ...interface{}) (n [int](#int), err [error](#error))
Fprint采用默认格式将其参数格式化并写入w。如果两个相邻的参数都不是字符串,会在它们的输出之间添加空格。返回写入的字节数和遇到的任何错误。
func Sprint
func Sprint(a ...interface{}) [string](#string)
Sprint采用默认格式将其参数格式化,串联所有输出生成并返回一个字符串。如果两个相邻的参数都不是字符串,会在它们的输出之间添加空格。
func Println
func Println(a ...interface{}) (n [int](#int), err [error](#error))
Println采用默认格式将其参数格式化并写入标准输出。总是会在相邻参数的输出之间添加空格并在输出结束后添加换行符。返回写入的字节数和遇到的任何错误。
func Fprintln
func Fprintln(w [io](https://studygolang.com/static/pkgdoc/pkg/io.htm).[Writer](#Writer), a ...interface{}) (n [int](#int), err [error](#error))
Fprintln采用默认格式将其参数格式化并写入w。总是会在相邻参数的输出之间添加空格并在输出结束后添加换行符。返回写入的字节数和遇到的任何错误。
func Sprintln
func Sprintln(a ...interface{}) [string](#string)
Sprintln采用默认格式将其参数格式化,串联所有输出生成并返回一个字符串。总是会在相邻参数的输出之间添加空格并在输出结束后添加换行符。
package main
import (
"fmt"
"os"
)
func main() {
var a,b string
a,b = "hello","world"
//Print采用默认格式将其参数格式化并写入标准输出。如果两个相邻的参数都不是字符串,会在它们的输出之间添加空格。返回写入的字节数和遇到的任何错误。
fmt.Print("01a ",a," ",b,"\n")
//Println采用默认格式将其参数格式化并写入标准输出。总是会在相邻参数的输出之间添加空格并在输出结束后添加换行符。返回写入的字节数和遇到的任何错误。
fmt.Println("01b ",a," ",b)
//Fprint采用默认格式将其参数格式化并写入w。如果两个相邻的参数都不是字符串,会在它们的输出之间添加空格。返回写入的字节数和遇到的任何错误。
fmt.Fprint(os.Stdout,"02a ",a,` `,b,"\n")
//Fprintln采用默认格式将其参数格式化并写入w。总是会在相邻参数的输出之间添加空格并在输出结束后添加换行符。返回写入的字节数和遇到的任何错误。
fmt.Fprintln(os.Stdout,"02b ",a,` `,b)
//Sprint采用默认格式将其参数格式化,串联所有输出生成并返回一个字符串。如果两个相邻的参数都不是字符串,会在它们的输出之间添加空格。
ab := fmt.Sprint("03a ",a,` `,b)
fmt.Println(ab)
//Sprintln采用默认格式将其参数格式化,串联所有输出生成并返回一个字符串。总是会在相邻参数的输出之间添加空格并在输出结束后添加换行符。
ab = fmt.Sprintln("03b ",a,` `,b)
fmt.Print(ab)
}
输出:
01a hello world
01b hello world
02a hello world
02b hello world
03a hello world
03b hello world
func Errorf
func Errorf(format [string](#string), a ...interface{}) [error](#error)
Errorf根据format参数生成格式化字符串并返回一个包含该字符串的错误。
package main
import (
"errors"
"fmt"
)
func main() {
//Errorf根据format参数生成格式化字符串并返回一个包含该字符串的错误。
err1 := fmt.Errorf("invalid contents: %s", "#$%")
err2 := errors.New(fmt.Sprintf("invalid contents: %s", "#$%"))
if err1.Error() == err2.Error() {
fmt.Println("The error messages in err1 and err2 are the same.")
}
}
输出:
The error messages in err1 and err2 are the same.
几种输入方式的区别
Scan、Scanf 和 Scanln 从os.Stdin 中读取;
func Scan
func Scan(a ...interface{}) (n [int](#int), err [error](#error))
Scan从标准输入扫描文本,将成功读取的空白分隔的值保存进成功传递给本函数的参数。换行视为空白。返回成功扫描的条目个数和遇到的任何错误。如果读取的条目比提供的参数少,会返回一个错误报告原因。
func Scanf
func Scanf(format [string](#string), a ...interface{}) (n [int](#int), err [error](#error))
Scanf从标准输入扫描文本,根据format 参数指定的格式将成功读取的空白分隔的值保存进成功传递给本函数的参数。返回成功扫描的条目个数和遇到的任何错误。
func Scanln
func Scanln(a ...interface{}) (n [int](#int), err [error](#error))
Scanln类似Scan,但会在换行时才停止扫描。最后一个条目后必须有换行或者到达结束位置。
package main
import "fmt"
func main() {
var str,str2,str3 string
//Scan从标准输入扫描文本,将成功读取的空白分隔的值保存进成功传递给本函数的参数。换行视为空白。返回成功扫描的条目个数和遇到的任何错误。如果读取的条目比提供的参数少,会返回一个错误报告原因。
fmt.Scan(&str)
fmt.Printf("您输入的值是:%v\n",str)
//Scanf从标准输入扫描文本,根据format 参数指定的格式将成功读取的空白分隔的值保存进成功传递给本函数的参数。返回成功扫描的条目个数和遇到的任何错误。
fmt.Scanf("%v",&str2)
fmt.Printf("您输入的值是:%v\n",str2)
//Scanln类似Scan,但会在换行时才停止扫描。最后一个条目后必须有换行或者到达结束位置。
fmt.Scanln(&str3)
fmt.Printf("您输入的值是:%v",str3,)
}
输出:
虎
您输入的值是:虎
呛
您输入的值是:呛
哥
您输入的值是:哥
Fscan、Fscanf 和 Fscanln 从指定的 io.Reader 中读取;
func Fscan
func Fscan(r [io](https://studygolang.com/static/pkgdoc/pkg/io.htm).[Reader](#Reader), a ...interface{}) (n [int](#int), err [error](#error))
Fscan从r扫描文本,将成功读取的空白分隔的值保存进成功传递给本函数的参数。换行视为空白。返回成功扫描的条目个数和遇到的任何错误。如果读取的条目比提供的参数少,会返回一个错误报告原因。
func Fscanf
func Fscanf(r [io](https://studygolang.com/static/pkgdoc/pkg/io.htm).[Reader](#Reader), format [string](#string), a ...interface{}) (n [int](#int), err [error](#error))
Fscanf从r扫描文本,根据format 参数指定的格式将成功读取的空白分隔的值保存进成功传递给本函数的参数。返回成功扫描的条目个数和遇到的任何错误。
func Fscanln
func Fscanln(r [io](https://studygolang.com/static/pkgdoc/pkg/io.htm).[Reader](#Reader), a ...interface{}) (n [int](#int), err [error](#error))
Fscanln类似Fscan,但会在换行时才停止扫描。最后一个条目后必须有换行或者到达结束位置。
package main
import (
"fmt"
"strings"
)
func main() {
var str string
r := strings.NewReader("虎呛哥元宇宙")
//Fscan从r扫描文本,将成功读取的空白分隔的值保存进成功传递给本函数的参数。换行视为空白。返回成功扫描的条目个数和遇到的任何错误。如果读取的条目比提供的参数少,会返回一个错误报告原因。
fmt.Fscan(r,&str)
fmt.Println(str)
//Fscanf从r扫描文本,根据format 参数指定的格式将成功读取的空白分隔的值保存进成功传递给本函数的参数。返回成功扫描的条目个数和遇到的任何错误。
fmt.Fscanf(r,"%v",&str)
fmt.Println(str)
//Fscanln类似Fscan,但会在换行时才停止扫描。最后一个条目后必须有换行或者到达结束位置。
fmt.Fscanln(r,"%v",&str)
fmt.Print(str)
}
输出:
虎呛哥元宇宙
虎呛哥元宇宙
虎呛哥元宇宙
Sscan、Sscanf 和 Sscanln 从实参字符串中读取。
func Sscan
func Sscan(str [string](#string), a ...interface{}) (n [int](#int), err [error](#error))
Sscan从字符串str扫描文本,将成功读取的空白分隔的值保存进成功传递给本函数的参数。换行视为空白。返回成功扫描的条目个数和遇到的任何错误。如果读取的条目比提供的参数少,会返回一个错误报告原因。
func Sscanf
func Sscanf(str [string](#string), format [string](#string), a ...interface{}) (n [int](#int), err [error](#error))
Sscanf从字符串str扫描文本,根据format 参数指定的格式将成功读取的空白分隔的值保存进成功传递给本函数的参数。返回成功扫描的条目个数和遇到的任何错误。
func Sscanln
func Sscanln(str [string](#string), a ...interface{}) (n [int](#int), err [error](#error))
Sscanln类似Sscan,但会在换行时才停止扫描。最后一个条目后必须有换行或者到达结束位置。
package main
import "fmt"
func main() {
var name,word,life,time,open,now string
//Sscan从字符串str扫描文本,将成功读取的空白分隔的值保存进成功传递给本函数的参数。换行视为空白。返回成功扫描的条目个数和遇到的任何错误。如果读取的条目比提供的参数少,会返回一个错误报告原因。
fmt.Sscan("虎呛哥 元宇宙",&name,&word)
fmt.Println(name,word)
//Sscanf从字符串str扫描文本,根据format 参数指定的格式将成功读取的空白分隔的值保存进成功传递给本函数的参数。返回成功扫描的条目个数和遇到的任何错误。
fmt.Sscanf("专注元宇宙 30年","%v %v",&life,&time)
fmt.Println(life,"--",time)
//Sscanln类似Sscan,但会在换行时才停止扫描。最后一个条目后必须有换行或者到达结束位置。
fmt.Sscanln("开始时间 2021年",&open,&now)
fmt.Println(open," ",now)
}
输出:
虎呛哥 元宇宙
专注元宇宙 -- 30年
开始时间 2021年
Scanln、Fscanln 和 Sscanln 在换行符处停止扫描,且需要条目紧随换行符之后;
Scanf、Fscanf 和 Sscanf 需要输入换行符来匹配格式中的换行符;其它函数则将换行符视为空格。