〇、关于 fmt

fmt 标准库是 Go 语言标准库的一部分,提供了格式化字符串、输入输出等基本功能。通过 fmt 库,我们可以进行简单的格式化输出、读取用户输入、错误输出等操作。

fmt 库实现了类似 C 语言 printf 和 scanf 的格式化 I/O,主要分为向外输出内容和获取输入内容两大部分,本文将通过示例来分别测试。

一、输出

GO 语言的输出是由 Print 系列函数完成的,下面列一下都有哪些输出类型。

1.1 Print-直接输出

Print 函数直接输入内容到终端,是最简单的输出方式。

package main

import (
"fmt"
) func main() {
fmt.Print("第一段")
fmt.Print("第二段")
fmt.Print("第三段")
}

由输出可见,Print 函数直接输出引号中的内容,不进行任何修饰。

1.2 Printf-以指定格式输出

fmt.Printf 是 Go 语言 fmt 包中的一个函数,用于格式化输出字符串。

它的基本语法是 fmt.Printf(format, a, b, c, ...),其中 format 是一个字符串,用于指定输出的格式,a, b, c, ... 是需要输出的参数。fmt.Printf 会按照 format 字符串中的格式说明符,将参数转换为相应的格式输出。

对于 format 中的格式说明,有比较多格式配置,下面总结下。

1.2.1 通用占位符

占位符 说明
%v 根据值的默认格式标识仅输出值
%+v 在 v% 的基础上,带上字段名
%#v 按照值的 GO 语法表示输出,类型+值
%T 输出值的类型
%% 输出单个字符:百分号

下面通过输出三个类型(常量、字符串、自定义结构)来简单演示下:

package main

import "fmt"

func main() {
pi := 3.1415926
fmt.Printf("%%v-pi :%v \n", pi) // %v 值的类型输出
fmt.Printf("%%+v :%+v \n", pi)
fmt.Printf("%%#v :%#v \n", pi)
fmt.Printf("%%T :%T \n", pi)
str := "chengzi"
fmt.Printf("%%v-str:%v \n", str)
fmt.Printf("%%+v :%+v \n", str)
fmt.Printf("%%#v :%#v \n", str)
fmt.Printf("%%T :%T \n", str)
stu := struct {
name string
address string
}{"橙子", "河南"}
fmt.Printf("%%v-stu:%v \n", stu)
fmt.Printf("%%+v :%+v \n", stu)
fmt.Printf("%%#v :%#v \n", stu)
fmt.Printf("%%T :%T \n", stu)
}

1.2.2 布尔类型占位符

针对布尔类型,有个专用的占位符:%t,用于直接输出 true/false

如果要输出的字段不是布尔类型,不会中断程序运行,只会有警告提示。

package main

import "fmt"

func main() {
fmt.Printf("%%t :%t \n", true)
fmt.Printf("%%t :%t \n", false)
fmt.Printf("%%t :%t \n", "chengzi")
}

1.2.3 整型数值占位符

占位符 说明
%b 输出值对应的二进制格式值
%c 输出值对应的 Unicode 码值
%d 输出值对应的十进制格式值
%o 输出值对应的八进制格式值
%x 输出值对应的十六进制格式值,小写字母 a~f
%X 输出值对应的十六进制格式值,大写字母 A~F
%U 输出值对应的 Unicode 格式:U+1234
%q 该值对应的单引号括起来的 Go 语法字符字面值,必要时会采用安全的转义表示

注:统一码(Unicode),也叫万国码、单一码,由统一码联盟开发,是计算机科学领域里的一项业界标准,包括字符集、编码方案等。其中 3400-4DBF/4E00-9FFF/20000-3FFFF,表示中日韩越统一表意文字(CJKV Unified Ideographs)。

如下通过对整数 100 的多类型输出,示例说明一下各个占位符对应的区别:

package main

import "fmt"

func main() {
num := 100
fmt.Printf("%%b :%b\n", num)
fmt.Printf("%%c :%c\n", num)
fmt.Printf("%%d :%d\n", num)
fmt.Printf("%%o :%o\n", num)
fmt.Printf("%%x :%x\n", num)
fmt.Printf("%%X :%X\n", num)
fmt.Printf("%%U :%U\n", num)
fmt.Printf("%%q :%q\n", num)
}

1.2.4 浮点数占位符

占位符 说明
%e 科学计数法,小写字母:-1.234567e+89
%E 科学计数法,大写字母:-1.234567E+89
%f 有小数(六位)、无指数:123.456789
%F 同上
%g 以使用更简洁、准确的格式输出为目的,灵活采用 %e 或 %f 格式,小数保留前十四位
%G 以使用更简洁、准确的格式输出为目的,灵活采用 %E 或 %F 格式
package main

import "fmt"

func main() {
f := 123.45600
fmt.Printf("f-%%e :%e\n", f)
fmt.Printf("f-%%E :%E\n", f)
fmt.Printf("f-%%f :%f\n", f)
fmt.Printf("f-%%F :%F\n", f)
fmt.Printf("f-%%g :%g\n", f) // 最多保留十四位小数
fmt.Printf("f-%%G :%G\n", f) // 最多保留十四位小数
ff := 123.4560001001000111001000011001
fmt.Printf("ff-%%e :%e\n", ff)
fmt.Printf("ff-%%E :%E\n", ff)
fmt.Printf("ff-%%f :%f\n", ff)
fmt.Printf("ff-%%F :%F\n", ff)
fmt.Printf("ff-%%g :%g\n", ff) // 最多保留十四位小数,末尾若是 0 默认省去
fmt.Printf("ff-%%G :%G\n", ff) // 最多保留十四位小数
}

1.2.5 字符串和 []byte 占位符

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

import "fmt"

func main() {
str := "橙子"
fmt.Printf("%%s: %s\n", str)
fmt.Printf("%%q: %q\n", str)
fmt.Printf("%%x: %x\n", str)
fmt.Printf("%%X: %X\n", str)
byte := []byte("橙子")
fmt.Printf("%%v: %v\n", byte)
fmt.Printf("%%s: %s\n", byte)
}

1.2.6 指针占位符

指针也是一个专门的占位符 %p,表示‘十六进制字符串’+‘0x’

package main

import "fmt"

func main() {
a := 18
fmt.Printf("%p\n", &a)
fmt.Printf("%#p\n", &a)
}

1.2.7 宽度标识符

宽度标识符就是以浮点数占位符中的 %f 为基础,增加宽度配置。%[n].[m]f 其中 n 表示整个数值的宽度,m 表示小数位宽度。如下示例与代表的意义:

占位符 说明
%f 默认宽度、默认精度
%9f 宽度 9、默认精度
%.2f 默认宽度、精度 2
%9.2f 宽度 9、精度 2
%9.f 宽度 9、精度 0

注意:小数点也占用一个位数。

package main

import "fmt"

func main() {
n := 88.88
fmt.Printf("%%f :%f\n", n) // 默认小数位为六位
fmt.Printf("%%9f :%9f\n", n)
fmt.Printf("%%10f :%10f\n", n)
fmt.Printf("%%.2f :%.2f\n", n)
fmt.Printf("%%9.2f :%9.2f\n", n)
fmt.Printf("%%9.f :%9.f\n", n)
}

1.2.8 其他占位符

占位符 说明
+ 总是输出数值的正负号;对 %q(%+q)会生成全部是 ASCII 字符的输出(通过转义)
 (一个空格)

对数值:正数前加空格而负数前加负号

对字符串:采用%x或%X时(% x或% X)会给各打印的字节之间加空格

-(一个横杠) 在输出右边填充空白,而不是默认的左边(即从默认的右对齐切换为左对齐)
#

八进制数前加 0(%#o)

十六进制数前加 0x,对于 %x(%#x);0X,对于 %X(%#X)

指针去掉前面的 0x,对于 %q(%#q),

unicode 值,对 %U(%#U)会输出空格和单引号括起来的 Go 字面值

0 使用 0 而不是空格填充,对于数值类型会把填充的 0 放在正负号后面
package main

import "fmt"

func main() {
fmt.Println("-----------------------------")
num := -12.34
num1 := 12.34
fmt.Printf("%f %f\n", num, num1)
fmt.Printf("%+f %+f\n", num, num1)
fmt.Println("-----------------------------")
num2 := -12.34
num3 := 12.34
fmt.Printf("%f %f\n", num2, num3)
fmt.Printf("% f % f\n", num2, num3)
str := "chengzi"
fmt.Printf("%x\n% x\n", str, str)
fmt.Println("-----------------------------")
num4 := 77.77
fmt.Printf("%10f\n", num4)
fmt.Printf("%0-10f\n", num4)
fmt.Println("-----------------------------")
str1 := "chengzi"
fmt.Printf("%s\n", str1)
fmt.Printf("%8s\n", str1) // 默认左侧填充一个空格,右对齐
fmt.Printf("%-8s\n", str1) // 左对齐
fmt.Printf("%08s\n", str1) // 填充 0
fmt.Printf("%-08s\n", str1) // 左对齐并填充 0,可以左对齐,但此时填充无法实现
}

1.3 Println-输出后自动换行

其实 Println 就是在打印输出内容后添加一个换行符‘\n’。

package main

import "fmt"

func main() {
fmt.Print("Println测试")
fmt.Println("-----------------------------")
fmt.Print("Println测试")
}

横线直接跟在了第一行,第二个输出自动进行了换行。

1.4 Fprint-将内容写入文件

Fprint 系列函数会将内容输出到一个 io.Writer 接口类型的变量 w 中,我们通常用这个函数往文件中写入内容

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)

package main

import (
"fmt"
"os"
) func main() {
fmt.Println("开始向标准输出写入内容...")
fileObj, err := os.OpenFile("./log.txt", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
// O_CREATE(不存在则创建)O_WRONLY(只写)O_APPEND(追加内容)
if err != nil {
fmt.Println("打开文件出错,err:", err)
return
}
content := "chengzi子"
// 向打开的文件句柄中写入内容
fmt.Fprintf(fileObj, "往文件中写入信息:%s\n", content)
fmt.Fprintln(fileObj, "又一行信息。")
fmt.Fprint(fileObj, "再一行信息。")
fmt.Fprint(fileObj, "最后的信息。")
fmt.Println("写入完成!")
}

终端输出:

1.5 Sprint-将传入的数据以字符串形式输出

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

package main

import (
"fmt"
) func main() {
s1 := fmt.Sprint("chengzi家")
fmt.Println(s1)
s2 := fmt.Sprintln("chengzi家")
fmt.Println(s2)
name := "chengzi家"
age := 18
s3 := fmt.Sprintf("name:%s,age:%d", name, age)
fmt.Println(s3)
}

1.6 Errorf-返回一个包装后的错误(errors.Wrap 简介

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

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

fmt.Errorf 的优点在于其支持格式化字符串,这使得我们可以方便地在原始错误信息中包含一些动态的数据,但是它并不会保留原始错误的堆栈跟踪信息。

Go 1.13 中引入的新特性使 fmt.Errorf 通过 %w 谓词包装错误,这样就可以保留原始错误的信息。如下:

package main

import (
"errors"
"fmt"
) func main() {
original_err := errors.New("original error")
new_err := fmt.Errorf("an error occurred: %w", original_err)
fmt.Println(new_err)
}

另外,errors.Wrap 和 errors.Wrapf 是包含原始错误的堆栈跟踪信息。它们是 github.com/pkg/errors 库中的函数,用于创建新的错误。它们接受一个原始错误和一个描述信息,返回一个新的错误,结构如下:

err := errors.Wrap(err, "an error occurred")
err = errors.Wrapf(err, "an error occurred: %s", "additional context")

errors.Wrap 和 errors.Wrapf 的优点在于它们会保留原始错误的堆栈跟踪信息。你可以使用 errors.Cause 函数获取到原始错误,使用 fmt.Printf("%+v", err) 打印完整的错误信息和堆栈跟踪。

此外,errors.Wrapf 还支持格式化字符串,这意味着我们可以在错误信息中直接包含动态的数据。如下一个关于 errors.Wrap 和 errors.Wrapf 的示例:

package main

import (
"fmt" "github.com/pkg/errors"
) func main() {
original_err := errors.New("original error")
new_err := fmt.Errorf("fmt.Errorf(): %w", original_err)
fmt.Println(new_err)
fmt.Println("------------------------------------------")
fmt.Println("------------------------------------------")
err := errors.Wrap(original_err, "errors.Wrap()")
fmt.Printf("fmt.Wrap():%+v\n", err)
fmt.Println("------------------------------------------")
fmt.Println("------------------------------------------")
err = errors.Wrapf(original_err, "errors.Wrapf(): %s", "additional context")
fmt.Printf("fmt.Wrapf():%+v\n", err)
}

1.6 参考:https://cloud.tencent.com/developer/article/2311646

二、输入

Go 语言 fmt 包下有 fmt.Scan、fmt.Scanf、fmt.Scanln 三个函数,可以在程序运行过程中从标准输入获取用户的输入。下面分别来介绍下。

2.1 fmt.Scan()-扫描客户端输入的文本参数值

Scan 从标准输入扫描文本,读取由空白符分割的值保存到传递给本函数的参数中,换行符或空格视为空白符

本函数返回成功扫描的数据个数和遇到的任何错误。如果读取的数据个数比提供的参数少,会返回一个错误描述原因。

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

package main

import (
"fmt"
) func main() {
var (
name string
age int
married bool
)
fmt.Println("请输入字符参数,回车确认输入完成:")
fmt.Scan(&name, &age, &married)
fmt.Printf("扫描结果 name:%s age:%d married:%t \n", name, age, married)
}

客户端手动输入多个字符参数时,用空格或换行分隔且可以混用,最后通过回车确认输入完成。如下是几个输入示例:

2.2 fmt.Scanf-扫描可指定格式的输入参数值

相较于 fmt.Scan(),fmt.Scanf() 可以定义输入参数的格式,只有按照指定格式输入才会识别,更加标准化。

Scanf 从标准输入扫描文本,根据 format 参数指定的格式去读取由空白符分隔的值保存到传递给本函数的参数中。

本函数返回成功扫描的数据个数和遇到的任何错误。

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

package main

import "fmt"

func main() {
var (
name string
age int
married bool
)
fmt.Println("请输入字符参数,回车确认输入完成:")
fmt.Scanf("1:%v 2:%v 3:%v", &name, &age, &married)
fmt.Printf("扫描结果 name:%s age:%d married:%t \n", name, age, married)
}

2.3 fmt.Scanln-最后通过回车确认输入参数值

相较于 fmt.Scan(),fmt.Scanln 不允许输入多个参数间回车,只能通过空格来分隔多个参数,最后回车确认输入。

Scanln 类似 Scan,它在遇到换行时才停止扫描。最后一个数据后面必须有换行或者到达结束位置。

本函数返回成功扫描的数据个数和遇到的任何错误。

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

package main

import "fmt"

func main() {
var (
name string
age int
married bool
)
fmt.Println("请输入字符参数,回车确认输入完成:")
fmt.Scanln(&name, &age, &married)
fmt.Printf("扫描结果 name:%s age:%d married:%t \n", name, age, married)
}

2.4 bufio.NewReader-读取包括空格在内的全部输入

当想获取完整获取输入的内容,但是输入的内容可能包含空格,这种情况下可以使用 bufio 包来实现。

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)
}

2.5 Fscan 系列-根据指定字符串扫描目标值

这几个函数功能分别类似于 fmt.Scan、fmt.Scanf、fmt.Scanln 三个函数,只不过它们不是从标准输入中读取数据而是从 io.Reader 中读取数据。注意:Fscan 系列都是和 io 阻塞的有关系。

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)

package main

import (
"fmt"
"strings"
) func main() {
var (
name string
age int
married bool
)
reader := strings.NewReader("chengzijia 18 false")
intt, _ := fmt.Fscan(reader, &name, &age, &married)
fmt.Printf("扫描结果 name:%s age:%d married:%t \n", name, age, married)
fmt.Printf("intt:%v\n", intt)
}

2.6 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)

package main

import "fmt"

func main() {
{ // Sscan
var name string
var alphabet_count int
n, err := fmt.Sscan("GFG 3", &name, &alphabet_count) // 根据空格取值
if err != nil {
panic(err)
}
fmt.Printf("%d:%s, %d\n", n, name, alphabet_count)
}
{ // Sscanln
var name string
var alphabet_count int
n, err := fmt.Sscanln("GFG 3", &name, &alphabet_count) // 根据空格取值
if err != nil {
panic(err)
}
fmt.Printf("n:%d, name:%s, alphabet_count:%d\n",
n, name, alphabet_count)
}
{ // Sscanf
var name string
var alphabet_count int
n, err := fmt.Sscanf("GFG is having 3 alphabets.", // 根据模板取值
"%s is having %d alphabets.", &name, &alphabet_count)
if err != nil {
panic(err)
}
fmt.Printf("%d:%s, %d\n", n, name, alphabet_count)
}
}

参考:http://www.topgoer.com/%E5%B8%B8%E7%94%A8%E6%A0%87%E5%87%86%E5%BA%93/fmt.html

fmt 库简介和示例【GO 基础】的更多相关文章

  1. Python3.x:第三方库简介

    Python3.x:第三方库简介 环境管理 管理 Python 版本和环境的工具 p – 非常简单的交互式 python 版本管理工具. pyenv – 简单的 Python 版本管理工具. Vex ...

  2. php spl标准库简介(SPL是Standard PHP Library(PHP标准库)(直接看代码实例,特别方便)

    php spl标准库简介(SPL是Standard PHP Library(PHP标准库)(直接看代码实例,特别方便) 一.总结 直接看代码实例,特别方便易懂 thinkphp控制器利眠宁不支持(说明 ...

  3. BerkeleyDB库简介

    BerkeleyDB库简介 BerkeleyDB(简称为BDB)是一种以key-value为结构的嵌入式数据库引擎: 嵌入式:bdb提供了一系列应用程序接口(API),调用这些接口很简单,应用程序和b ...

  4. LevelDB库简介

    LevelDB库简介 一.LevelDB入门 LevelDB是Google开源的持久化KV单机数据库,具有很高的随机写,顺序读/写性能,但是随机读的性能很一般,也就是说,LevelDB很适合应用在查询 ...

  5. Android查缺补漏(IPC篇)-- 进程间通讯之Socket简介及示例

    本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8425736.html 进程间通讯篇系列文章目录: Android查缺补漏(IP ...

  6. IdentityServer4 中文文档 -6- (简介)示例服务器和测试

    IdentityServer4 中文文档 -6- (简介)示例服务器和测试 原文:http://docs.identityserver.io/en/release/intro/test.html 目 ...

  7. mootools常用特性和示例(基础篇1)

    网上关于mootools这个库的信息很少. 公司一些老的项目用到了mootools库,因为要维护,所以接触到了mootools. mootools(文档)官网:http://www.chinamoot ...

  8. 【网络爬虫入门02】HTTP客户端库Requests的基本原理与基础应用

    [网络爬虫入门02]HTTP客户端库Requests的基本原理与基础应用 广东职业技术学院  欧浩源 1.引言 实现网络爬虫的第一步就是要建立网络连接并向服务器或网页等网络资源发起请求.urllib是 ...

  9. Ansible - 简介和应用自动化基础实践

    installAnsible简介和应用自动化基础实践 一.引入: 1.1  如官方定义,Ansible is The simplest way to automate apps and IT infr ...

  10. MXNet深度学习库简介

    MXNet深度学习库简介 摘要: MXNet是一个深度学习库, 支持C++, Python, R, Scala, Julia, Matlab以及JavaScript等语言; 支持命令和符号编程; 可以 ...

随机推荐

  1. 基于php的外卖订餐网站(php+mysql)

    介绍 一个基于php的外卖订餐网站,包括前端和后台. 效果演示 http://101.43.124.118:8001/admin 源码地址 https://github.com/geeeeeeeek/ ...

  2. 【leetcode】#647 回文子串 Rust Solution

    给定一个字符串,你的任务是计算这个字符串中有多少个回文子串.具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被视作不同的子串. 示例 1:输入:"abc"输出:3解释 ...

  3. 手撕HashMap(一)

    HashMap基本了解 1. jdk1.7之前,HashMap底层只是数组和链表 2. jdk1.8之后,HashMap底层数据结构当链表长度超过8时,会转为红黑树 3. HashMap利用空间换时间 ...

  4. 【Springboot】SpringBoot-Admin 服务监控+告警通知

    SpringBoot-Admin 服务监控 简单介绍 Spring Boot Actuator 是 Spring Boot 自带的一个功能模块, 提供了一组已经开箱即用的生产环境下常用的特性和服务,比 ...

  5. 3D降噪_时域降噪待补充

    视频去噪方法按照处理域的不同可分为空间域.频域.小波域.时域.时-空域去噪等,但是不同域之间的去噪方法会发生重叠现象,或者一种去噪方法会或涉及多个处理域.例如,在时域或时-空域去噪方法中也可使用频域的 ...

  6. adb如何做Android ui自动化(这一篇就够了)

    一.简介 我们都知道在做Android ui自动化的时候用的是appium,环境搭建贼难受.如果我们在工作中遇到需要实现简单的自动化功能,可以直接使用adb来完成,无需去搭建繁琐的appium.ADB ...

  7. java协程线程之虚拟线程

    前言 众所周知,java 是没有协程线程的,在我们如此熟知的jdk 1.8时代,大佬们想出来的办法就是异步io,甚至用并行的stream流来实现,高并发也好,缩短事件处理时间也好:大家都在想着自己认为 ...

  8. Hive安装与启动

    一.mysql安装 在配置Hive之前一般都需要安装和配置MySQL,因为Hive为了能操作HDFS上的数据集,那么他需要知道数据的切分格式,如行列分隔符,存储类型,是否压缩,数据的存储地址等信息. ...

  9. LiveCD 与 救援模式、紧急模式

    LiveCD 参考:live CD LiveCD 能够使你在不安装到硬盘的前提下,体验操作系统.大多数 Linux 桌面发行版都提供 LiveCD,这是宣传自己的一种很有效的方式. 救援模式 救援模式 ...

  10. linux文本编辑YCM报错

    linux文本编辑YCM报错 刚从github安装了vimplus,可是发现存在不少的问题.索性给直接记录一下. The ycmd server SHUT DOWN (restart with ':Y ...