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)