Golang 常用标准库 fmt 1x
fmt 包,实现了类似 C 语言 printf 和 scanf 的格式化 I/O,主要分为向外输出内容和获取输入内容两部分
向外输出内容
标准库 fmt,提供了以下几种输出相关函数:
(1)Print 系列:将内容输出到系统的标准输出,即:在命令行输出
// Print,直接输出内容 func Print(a ...interface{}) (n int, err error)
fmt.Print("在终端打印信息")
// Println,会在输出内容的结尾添加一个换行符 func Println(a ...interface{}) (n int, err error)
fmt.Println("在终端单独一行打印信息") // 说明:换行打印
// Printf,支持格式化输出字符串 func Printf(format string, a ...interface{}) (n int, err error)
name := "webpiece"
fmt.Printf("名称为:%s\n", name) // 名称为:webpiece
「 格式化占位符 」*printf 系列函数都支持 format 格式化参数,以下按照占位符将被替换的变量类型划分,方便查询和记忆
(1)通用占位符
// %v 值的默认格式表示 fmt.Printf("%v \n", 100) // 100 type Person struct { Name string Age int } p1 := Person{ Name: "小明", Age: 18, } // %+v,类似 %v,但,输出结构体时,会添加字段名 fmt.Printf("%v \n", p1) // {小明 18} fmt.Printf("%+v \n", p1) // {Name:小明 Age:18} // %#v,值的 GO 语法表示 fmt.Printf("%#v \n", p1) // main.Person{Name:"小明", Age:18} // %T,打印值的类型 fmt.Printf("%T \n", 100) // int fmt.Printf("%T \n", p1) // main.Person // %%,百分号 fmt.Printf("100%% \n") // 100%(2)不同的数据类型
//(1)布尔型 // %t,true 或 false fmt.Printf("%t", 10 > 5) // true //(2)整型 num := 1205 // %b,表示为二进制 fmt.Printf("%b \n", num) // 10010110101 // %c,该值对应的unicode码值 fmt.Printf("%c \n", num) // %d,表示为十进制 fmt.Printf("%d \n", num) // 1205 // %o,表示为八进制 fmt.Printf("%o \n", num) // 2265 // %x,表示为十六进制,使用a-f fmt.Printf("%x \n", num) // 4b5 // %X,表示为十六进制,使用A-F fmt.Printf("%X \n", num) // 4B5 // %U,表示为Unicode格式:U+1234,等价于”U+%04X” fmt.Printf("%U \n", num) // U+04B5 // %q,该值对应的单引号括起来的go语法字符字面值,必要时会采用安全的转义表示 fmt.Printf("%q \n", num) //(3)浮点型 f := 12.34 // %b,无小数部分、二进制指数的科学计数法,如-123456p-78 fmt.Printf("%b \n", f) // 6946802425218990p-49 // %e / %E,科学计数法,如-1234.456e+78 fmt.Printf("%e \n", f) // 1.234000e+01 fmt.Printf("%E \n", f) // 1.234000e+01 // %f / %F,有小数部分但无指数部分,如123.456 fmt.Printf("%f \n", f) // 12.340000 fmt.Printf("%F \n", f) // 12.340000 // 根据实际情况采用%e或%f格式(以获得更简洁、准确的输出) fmt.Printf("%g \n", f) // 12.34 // 根据实际情况采用%E或%F格式(以获得更简洁、准确的输出) fmt.Printf("%G \n", f) // 12.34 //(4)字符串 和 []byte s := "webpiece" // %s,直接输出字符串或者[]byte fmt.Printf("%s \n", s) // webpiece // %q,该值对应的双引号括起来的go语法字符串字面值,必要时会采用安全的转义表示 fmt.Printf("%q \n", s) // "webpiece" // %x,每个字节用两字符十六进制数表示(使用a-f) fmt.Printf("%x \n", s) // 7765627069656365 // %X,每个字节用两字符十六进制数表示(使用A-F) fmt.Printf("%X \n", s) // 7765627069656365 //(5)指针 // %p,表示为十六进制,并加上前导的0x a := 10 fmt.Println(&a) // 0x140000a4040 fmt.Printf("%p \n", &a) // 0x140000a4040 fmt.Printf("%#p \n", &a) // 140000a4040(3)
宽度标识符
- 宽度,通过一个紧跟在百分号后面的十进制数指定
- 如果未指定宽度,则表示值时,除必需之外不作填充
- 精度通过(可选的)宽度后跟点号后跟的十进制数指定
- 如果未指定精度,会使用默认精度;如果点号后,没有跟数字,表示精度为0
n := 12.34 // %f,默认宽度,默认精度 fmt.Printf("%f \n", n) // 12.340000 // %9f,宽度9,默认精度 fmt.Printf("%9f \n", n) // 12.340000 // %.2f,默认宽度,精度2 fmt.Printf("%.2f \n", n) // 12.34 // %9.2f,宽度9,精度2 fmt.Printf("%9.2f \n", n) // 12.34 // %9.f,宽度9,精度0 fmt.Printf("%9.f \n", n) // 12(4)
其他标识// ’+’ 总是输出数值的正负号;对%q(%+q)会生成全部是ASCII字符的输出(通过转义); // ’ ‘ 对数值,正数前加空格而负数前加负号;对字符串采用%x或%X时(% x或% X)会给各打印的字节之间加空格 // ’-’ 在输出右边填充空白而不是默认的左边(即从默认的右对齐切换为左对齐); // ‘0’ 使用0而不是空格填充,对于数值类型会把填充的0放在正负号后面 s := "web" fmt.Printf("%s\n", s) // web fmt.Printf("%5s\n", s) // web fmt.Printf("%-5s\n", s) // web fmt.Printf("%5.7s\n", s) // web fmt.Printf("%-5.7s\n", s) // web fmt.Printf("%5.2s\n", s) // we fmt.Printf("%05s\n", s) // 00web
(2)Fprint 系列:将内容输出到一个 io.Writer 接口类型的变量中,通常用来往文件中写入内容
func Fprint(w io.Writer, a ...interface{}) (n int, err error)
func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error)
func Fprintln(w io.Writer, a ...interface{}) (n int, err error)
// 只要满足 io.Writer 类型的接口都支持
// 代码示例:
// 向标准输出写入内容
fmt.Fprintln(os.Stdout, "向标准输出写入内容")
fileObj, err := os.OpenFile("./xx.txt", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
if err != nil {
fmt.Println("打开文件出错,err:", err)
return
}
name := "webpiece"
// 向打开的文件句柄中写入内容
fmt.Fprintf(fileObj, "往文件中写如信息:%s", name)
(3)Sprint 系列:把传入的内容,生成并返回一个字符串
func Sprint(a ...interface{}) string
func Sprintf(format string, a ...interface{}) string
func Sprintln(a ...interface{}) string
// 代码示例
str1 := fmt.Sprint("hello")
fmt.Println(str1) // hello
str2 := fmt.Sprintln("world") // 会换行
fmt.Print(str2) // world
// 格式化,并返回一个字符串,可以用来拼接字符串
name := "webpiece"
age := 20
str3 := fmt.Sprintf("名字:%s,年龄:%d \n", name, age)
fmt.Print(str3) // 名字:webpiece,年龄:20
(4)Errorf() 函数:格式化字符串,并返回一个包含该字符串的错误
func Errorf(format string, a ...interface{}) error
// 可以用来自定义错误类型
err1 := fmt.Errorf("这是一个错误")
fmt.Printf("类型:%T,内容:%s", err1, err1) // 类型:*errors.errorString,内容:这是一个错误
// Go1.13 为 fmt.Errorf 函数,新加了一个 %w 占位符,用来生成一个可以包裹 Error 的 Wrapping Error
err := errors.New("原始错误") // 原始错误
err2 := fmt.Errorf("包裹了一个错误:%w", err)
fmt.Printf("类型:%T,内容:%s", err2, err2) // 类型:*fmt.wrapError,内容:包裹了一个错误:原始错误
获取输入内容
(1)Scan 系列:从标准输入中读取数据
fmt 包,提供了 fmt.Scan、fmt.Scanf、fmt.Scanln 三个函数,可以在程序运行过程中,从标准输入获取用户的输入
- fmt.Scan:以空格作为输入数据的分隔符
// fmt.Scan // 基本语法:func Scan(a ...interface{}) (n int, err error) // 作用:从标准输入扫描用户输入的数据,将以空白符( 换行符,视为空白符 )分隔的数据,保存到传递给本函数的参数中 // 代码示例 1 var str string fmt.Scan(&str) // 命令行中输入:hello fmt.Println("str 为:" + str) // str 为:hello // 代码示例 2 var ( name string age int married bool ) // 本函数返回:成功扫描的数据个数和遇到的任何错误。如果读取的数据个数比提供的参数少,会返回一个错误报告原因 num, err := fmt.Scan(&name, &age, &married) // 命令行中输入( 以空格分隔 ):world 20 false fmt.Printf("扫描结果 name:%s age:%d married:%t \n", name, age, married) // 扫描结果 name:world age:20 married:false fmt.Println(num) if err != nil { fmt.Println(err) }
- fmt.Scanln( 较为常用 ):类似 Scan,它在遇到换行时,停止扫描
// fmt.Scanln // 基本语法:func Scanln(a ...interface{}) (n int, err error) // 作用:类似Scan,它在遇到换行时才停止扫描,最后一个数据后面必须有换行或者到达结束位置;返回成功扫描的数据个数和遇到的任何错误 var ( name string age int married bool ) fmt.Scanln(&name, &age, &married) // 在终端中输入:world 20 false,然后,回车,结束扫描 fmt.Printf("扫描结果 name:%s age:%d married:%t \n", name, age, married) // 扫描结果 name:world age:20 married:false
- fmt.Scanf:为输入数据规定了具体的输入内容格式
// fmt.Scanf // 基本语法:func Scanf(format string, a ...interface{}) (n int, err error) // 作用:从标准输入扫描文本,根据format参数指定的格式去读取由空白符分隔的值,保存到传递给本函数的参数中;返回成功扫描的数据个数和遇到的任何错误 var ( name string age int married bool ) fmt.Scanf("1:%s 2:%d 3:%t", &name, &age, &married) // 在命令行中输入:1:world 2:20 3:false fmt.Printf("扫描结果 name:%s age:%d married:%t \n", name, age, married) // 扫描结果 name:world age:20 married:false // 说明:不同于 fmt.Scan 简单的以空格作为输入数据的分隔符,fmt.Scanf 为输入数据规定了具体的输入内容格式,只有按照格式输入数据,才会被扫描并存入对应变量
(2)bufio.NewReader
有时候,我们想完整获取输入的内容,而输入的内容可能包含空格,这种情况下,可以使用 bufio 包来实现
func bufioDemo() { reader := bufio.NewReader(os.Stdin) // 从标准输入生成读对象 fmt.Print("请输入内容:") text, _ := reader.ReadString('\n') // 读到换行 text = strings.TrimSpace(text) fmt.Printf("%#v\n", text) }
(3)Fscan 系列:从 io.Reader 中读取数据
类似于 fmt.Scan、fmt.Scanf、fmt.Scanln ,只不过它们不是从标准输入中读取数据,而是从 io.Reader 中读取数据
func Fscan(r io.Reader, a ...interface{}) (n int, err error) func Fscanln(r io.Reader, a ...interface{}) (n int, err error) func Fscanf(r io.Reader, format string, a ...interface{}) (n int, err error)
(4)Sscan 系列:从指定字符串中读取数据
类似于 fmt.Scan、fmt.Scanf、fmt.Scanln,只不过它们不是从标准输入中读取数据,而是从指定字符串中读取数据
func Sscan(str string, a ...interface{}) (n int, err error) func Sscanln(str string, a ...interface{}) (n int, err error) func Sscanf(str string, format string, a ...interface{}) (n int, err error)