Go 之 fmt 格式化输入输出

向外输出

Print

Print系列函数会将内容输出到系统的标准输出,区别在于Print函数直接输出内容,Printf函数支持格式化输出字符串,Println函数会在输出内容的结尾添加一个换行符。

Go 复制代码
package main

import (
	"fmt"
)

func main() {
	// Print、Printf、Println
	fmt.Print("在终端打印该信息。") // 内容输出到标准输出
	name := "Looking"
	fmt.Printf("我是:%s\n", name) // 支持格式化输出
	fmt.Println("在终端打印单独一行显示")
}
Go 复制代码
在终端打印该信息。我是:Looking
在终端打印单独一行显示

Fprint

Fprint系列函数(Fprint、Fprintf、Fprintln)与 Print 系列函数(Print、Printf、Println)类似,只不过会将内容输出到一个io.Writer接口类型的变量w中,我们通常用这个函数往文件中写入内容。只要满足io.Writer接口的类型都支持写入。

Go 复制代码
package main

import (
	"fmt"
	"os"
)

func main() {
	// Fprint、Fprintf、Fprintln
	name := "Looking"
	fmt.Fprint(os.Stdout, "向标准输出写入内容且不换行!")
	fmt.Fprintln(os.Stdout, "向标准输出写入内容且换行!")
	fileObj, err := os.Create("./test.txt")
	if err != nil {
		fmt.Println("打开文件出错,err:", err)
		return
	}

	fmt.Fprintf(fileObj, "往文件中写如信息:%s", name) // 往文件对象输出
	// 文件: test.txt
	// 内容:往文件中写如信息:Looking
}
Go 复制代码
向标准输出写入内容且不换行!向标准输出写入内容且换行!

Sprint

Sprint系列函数(Sprint、Sprintf、Sprintln)与 Print 系列函数(Print、Printf、Println)类似,只不过不会直接输出,而是会把传入的数据生成并返回一个字符串。

Go 复制代码
package main

import (
	"fmt"
)

func main() {
	// Sprint、Sprintf、Sprintln
	name := "Looking"
	s1 := fmt.Sprint(name) // 返回字符串,字符串末尾不会自动添加换行符
	fmt.Print(s1)
	s2 := fmt.Sprintln(name) // 返回字符串,字符串末尾会自动添加换行符
	fmt.Print(s2)
	age := 18
	s3 := fmt.Sprintf("name:%s, age:%d", name, age) // 返回格式化后字符串
	fmt.Print(s3)
}
Go 复制代码
LookingLooking
name:Looking, age:18

Errorf

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

Go 复制代码
package main

import (
	"errors"
	"fmt"
)

func main() {
	// Errorf
	e := errors.New("原始错误e")
	w := fmt.Errorf("Wrap了一个错误:%w", e) // Wrap了一个错误:原始错误e
	fmt.Println(w.Error())
}

获取输入

Scan

Scan从标准输入扫描文本。

Go 复制代码
package main

import (
	"fmt"
)

func main() {
	var (
		name    string
		age     int
		married bool
	)
	fmt.Scan(&name, &age, &married) // 读取由空白符分隔的值保存到传递给本函数的参数中,换行符视为空白符。
	fmt.Printf("扫描结果 name:%s age:%d married:%t \n", name, age, married)
	// 输入:Looking 29 true
	// 输出:扫描结果 name:Looking age:29 married:true
	fmt.Scanf("1:%s 2:%d 3:%t", &name, &age, &married) // 根据format参数指定的格式去读取值保存到传递给本函数的参数中。
	fmt.Printf("扫描结果 name:%s age:%d married:%t \n", name, age, married)
	// 输入:1:Looking 2:29 3:true
	// 输出:扫描结果 name:Looking age:29 married:true
	fmt.Scanln(&name, &age, &married) // Scanln类似Scan,它在遇到换行时才停止扫描。
	fmt.Printf("扫描结果 name:%s age:%d married:%t \n", name, age, married)
	// 输入:Looking 29 true
	// 输出:扫描结果 name:Looking age:29 married:true
}

Fscan

这几个函数功能分别类似于fmt.Scanfmt.Scanffmt.Scanln三个函数,只不过它们不是从标准输入中读取数据而是从io.Reader中读取数据。

Go 复制代码
package main

import (
	"fmt"
	"os"
)

func main() {
	var (
		name    string
		age     int
		married bool
	)
	fileObj, err := os.OpenFile("./test.txt", os.O_RDONLY, 0644)
	if err != nil {
		fmt.Println("打开文件出错,err:", err)
		return
	}
	fmt.Fscan(fileObj, &name, &age, &married)
	fmt.Printf("扫描结果 name:%s age:%d married:%t \n", name, age, married)
	// test.txt:Looking 29 true
	// 输出:扫描结果 name:Looking age:29 married:true
	fmt.Fscanf(fileObj, "1:%s 2:%d 3:%t", &name, &age, &married)
	fmt.Printf("扫描结果 name:%s age:%d married:%t \n", name, age, married)
	// test.txt:1:Looking 2:29 3:true
	// 输出:扫描结果 name:Looking age:29 married:true
	fmt.Fscanln(fileObj, &name, &age, &married)
	fmt.Printf("扫描结果 name:%s age:%d married:%t \n", name, age, married)
	// test.txt:Looking 29 true
	// 输出:扫描结果 name:Looking age:29 married:true
}

Sscan

这几个函数功能分别类似于fmt.Scanfmt.Scanffmt.Scanln三个函数,只不过它们不是从标准输入中读取数据而是从指定字符串中读取数据。

Go 复制代码
package main

import (
	"fmt"
)

func main() {
	var (
		name    string
		age     int
		married bool
	)

	fmt.Sscan("Looking 29 true", &name, &age, &married)
	fmt.Printf("扫描结果 name:%s age:%d married:%t \n", name, age, married)
	// 输入:Looking 29 true
	// 输出:扫描结果 name:Looking age:29 married:true
	fmt.Sscanf("1:Looking 2:29 3:true", "1:%s 2:%d 3:%t", &name, &age, &married)
	fmt.Printf("扫描结果 name:%s age:%d married:%t \n", name, age, married)
	// 输入:1:Looking 2:29 3:true
	// 输出:扫描结果 name:Looking age:29 married:true
	fmt.Sscanln("Looking 29 true", &name, &age, &married)
	fmt.Printf("扫描结果 name:%s age:%d married:%t \n", name, age, married)
	// 输入:Looking 29 true
	// 输出:扫描结果 name:Looking age:29 married:true
}

NewReader

完整获取输入的内容并裁剪首尾空格

Go 复制代码
package main

import (
	"bufio"
	"fmt"
	"os"
	"strings"
)

func main() {
	reader := bufio.NewReader(os.Stdin) // 从标准输入生成读对象
	fmt.Print("请输入内容:")
	text, _ := reader.ReadString('\n') // 读到换行,分隔符后面的内容被忽略
	text = strings.TrimSpace(text) // 字符串头尾的空格会被移除
	fmt.Printf("%#v\n", text)
}
Go 复制代码
请输入内容:  hello world   
"hello world"

格式化输出

通用占位符

占位符 说明
%v 值的默认格式表示
%+v 类似%v,但输出结构体时会添加字段名
%#v 值的Go语法表示
%T 打印值的类型
%% 百分号
Go 复制代码
package main

import (
	"fmt"
)

func main() {
	fmt.Printf("%v\n", 100)   // 100
	fmt.Printf("%v\n", false) // false
	o := struct {
		name string
	}{"Looking"}
	fmt.Printf("%v\n", o)  // 打印值,{Looking}
	fmt.Printf("%#v\n", o) // 打印值,struct { name string }{name:"Looking"}
	fmt.Printf("%+v\n", o) // 打印值,输出结构体会添加字段名称 {name:Looking}
	fmt.Printf("%T\n", o)  // 打印值的类型,struct { name string }
	fmt.Printf("100%%\n")  // 100%
}

布尔型占位符

占位符 说明
%t true或false
Go 复制代码
package main

import "fmt"

func main() {
	b := true
	fmt.Printf("%t\n", b) // true
}

浮点数与复数

占位符 说明
%b 无小数部分、二进制指数的科学计数法,如-123456p-78
%e 科学计数法,如-1234.456e+78
%E 科学计数法,如-1234.456E+78
%f 有小数部分但无指数部分,如123.456
%F 等价于%f
%g 根据实际情况采用%e或%f格式(以获得更简洁、准确的输出)
%G 根据实际情况采用%E或%F格式(以获得更简洁、准确的输出)
Go 复制代码
package main

import "fmt"

func main() {
	f := 12.34
	fmt.Printf("%b\n", f) // 6946802425218990p-49
	fmt.Printf("%e\n", f) // 1.234000e+01
	fmt.Printf("%E\n", f) // 1.234000E+01
	fmt.Printf("%f\n", f) // 12.340000
	fmt.Printf("%g\n", f) // 12.34
	fmt.Printf("%G\n", f) // 12.34
}

字符串和\[\]byte

占位符 说明
%s 直接输出字符串或者\[\]byte
%q 该值对应的双引号括起来的go语法字符串字面值,必要时会采用安全的转义表示
%x 每个字节用两字符十六进制数表示(使用a-f )
%X 每个字节用两字符十六进制数表示(使用A-F)
Go 复制代码
package main

import "fmt"

func main() {
	s := "Looking"
	fmt.Printf("%s\n", s) // Looking
	fmt.Printf("%q\n", s) // "Looking"
	fmt.Printf("%x\n", s) // 4c6f6f6b696e67
	fmt.Printf("%X\n", s) // 4C6F6F6B696E67
}

指针占位符

占位符 说明
%p 表示为十六进制,并加上前导的0x
Go 复制代码
package main

import "fmt"

func main() {
	a := 10
	fmt.Printf("%p\n", &a)  // 0xc0000aa058
	fmt.Printf("%#p\n", &a) // c0000aa058
}

宽度标识符

宽度通过一个紧跟在百分号后面的十进制数指定,如果未指定宽度,则表示值时除必需之外不作填充。精度通过(可选的)宽度后跟点号后跟的十进制数指定。如果未指定精度,会使用默认精度;如果点号后没有跟数字,表示精度为0。举例如下:

占位符 说明
%f 默认宽度,默认精度
%9f 宽度9,默认精度
%.2f 默认宽度,精度2
%9.2f 宽度9,精度2
%9.f 宽度9,精度0
Go 复制代码
package main

import "fmt"

func main() {
	n := 12.34
	fmt.Printf("%f\n", n)    // 12.340000
	fmt.Printf("%9f\n", n)   // 12.340000
	fmt.Printf("%.2f\n", n)  // 12.34
	fmt.Printf("%9.2f\n", n) //     12.34
	fmt.Printf("%9.f\n", n)  //        12
}

其他占位符

占位符 说明
'+' 总是输出数值的正负号;对%q(%+q)会生成全部是ASCII字符的输出(通过转义);
' ' 对数值,正数前加空格而负数前加负号;对字符串采用%x或%X时(% x或% X)会给各打印的字节之间加空格
'-' 在输出右边填充空白而不是默认的左边(即从默认的右对齐切换为左对齐);
'#' 八进制数前加0(%#o),十六进制数前加0x(%#x)或0X(%#X),指针去掉前面的0x(%#p)对%q(%#q),对%U(%#U)会输出空格和单引号括起来的go字面值;
'0' 使用0而不是空格填充,对于数值类型会把填充的0放在正负号后面;
Go 复制代码
package main

import "fmt"

func main() {
	s := "Looking"
	fmt.Printf("%s\n", s)      // 字符串输出
	fmt.Printf("%10s\n", s)    // 宽度10,右对齐
	fmt.Printf("%-10s\n", s)   // 宽度10,左对齐
	fmt.Printf("%10.5s\n", s)  // 宽度10,右对齐,截取前5位
	fmt.Printf("%-10.5s\n", s) // 宽度10,左对齐,截取前5位
	fmt.Printf("%10.2s\n", s)  // 宽度10,右对齐,截取前2位
	fmt.Printf("%010s\n", s)   // 宽度10,右对齐,左边使用0填充
}
Go 复制代码
Looking
   Looking
Looking   
     Looki
Looki     
        Lo
000Looking
相关推荐
Bruce_Liuxiaowei2 分钟前
Python 实例赋值遮蔽类属性:一个从不报错的静默陷阱
开发语言·python·语法糖
IT_陈寒7 分钟前
Java线程池用错参数,我的服务居然悄悄崩溃了
前端·人工智能·后端
光影少年18 分钟前
Express 中间件原理
后端·node.js·express
aramae1 小时前
MySQL内置函数(7)
开发语言·笔记·后端·mysql·其他
徐小夕2 小时前
存量.doc 文档怎么办?JitWord 开源转换库打通旧文档到在线协同全链路
后端·架构·github
ee又momo2 小时前
一次 JWT Token 过期续期的踩坑记录
后端
五彩小白2 小时前
GO语言装饰器语法
golang
二月龙2 小时前
App 瘦身实战:图片、so 库、资源压缩,安装包体积减小 40%
后端
大勇前进2 小时前
Kotlin 协程实战避坑:90% 的人都会踩的生命周期泄漏问题
后端
苏三说技术3 小时前
Spring AI、LangChain4j、AgentScope、Embabel,哪个AI框架更好?
后端