Go fmt包 输出方式 有我就够了

662 阅读7分钟

fmt包对于新手经常用来调试、查看数据结果。

fmt.Print 和 fmt.Println两个函数,使用起来比较简单,容易上手。

fmt.Prinft 虽然灵活,却有一定的上手难度,想要完全掌握,需要不断的进行练习。

这篇文章已经全面,完全可以成为你在使用 fmt.Printf 时的使用手册,收藏起来。需要用到了就来查一查。

fmt.Print

func Print(a ...any) (n int, err error)

  • 使用参数默认格式打印格式并写入标准输出。

  • 当相邻两者都不是字符串,在操作数之间添加空格。

  • 它返回写入的字节数和遇到的任何写入错误。

举例:

type Obj struct {
   boolean bool
   str     string
   num     int
}


func main() {
   obj := &Obj{boolean: false, str: "string", num: 1}
   fmt.Print("hello", 1, "separator", true, "world", obj, 2)
}

//输出结果为: hello1separatortrueworld&{false string 1} 2

fmt.Println

func Println(a ...any) (n int, err error)

  • 使用参数默认格式打印格式并写入标准输出。

  • 在操作数之间总是添加空格,并且在结尾添加换行符号。

  • 它返回写入的字节数和遇到的任何写入错误。

func main() {
   const name, age = "Kim", 22
   fmt.Println(name, "is", age, "years old.") //Kim is 22 years old.
}

fmt.Printf

func Printf(format string, a ...any) (n int, err error)

  • 按照指定格式(format string) 打印格式并写入到标准输出。

  • 它返回写入的字节数和遇到的任何写入错误。

通用****占位符

  • %v:以值的默认格式打印

  • %+v:类似%v,但输出结构体时会添加字段名

  • %#v:值的Go语法表示

  • %T:打印值的类型

  • %%: 打印百分号本身

下面是具体代码:

package main

import "fmt"

type Obj struct {
   boolean bool
   str     string
   num     int
}

func main() {

   obj := &Obj{boolean: false, str: "string", num: 1}
   // 以值的默认格式打印
   fmt.Printf("%v\n", "hello") // hello
   fmt.Printf("%v\n", 1)       // 1
   fmt.Printf("%v\n", true)    // true
   fmt.Printf("%v\n", obj)     // &{false string 1}

   // 结构体特殊形式打印 【对比%v形式,多了字段名】
   fmt.Printf("%+v\n", "hello") // hello
   fmt.Printf("%+v\n", 1)       // 1
   fmt.Printf("%+v\n", true)    // true
   fmt.Printf("%+v\n", obj)     // &{boolean:false str:string num:1}

   // %#v:值的Go语法表示
   fmt.Printf("%#v\n", "hello") // "hello"      【注意这里多了引号】
   fmt.Printf("%#v\n", 1)       // 1
   fmt.Printf("%#v\n", true)    // true
   fmt.Printf("%#v\n", obj)     // &main.Obj{boolean:false, str:"string", num:1}

   // %T:值的Go语法表示
   fmt.Printf("%T\n", "hello") // string      【注意这里多了引号】
   fmt.Printf("%T\n", 1)       // int
   fmt.Printf("%T\n", true)    // bool
   fmt.Printf("%T\n", obj)     // *main.Obj

   fmt.Printf("%%\n") // output: %
}

打印布尔值

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

打印字符串

  • %s:输出字符串表示(string类型或[]byte)

  • %q:双引号围绕的字符串,由Go语法安全地转义

  • %x:十六进制,小写字母,每字节两个字符

  • %X:十六进制,大写字母,每字节两个字符

fmt.Printf("%s \n", []byte("Hello, Golang")) // output: Hello, Golang
fmt.Printf("%s \n", "Hello, Golang")         // output: Hello, Golang
fmt.Printf("%s \n", `Hello, \r\n Golang`)    // output: Hello, \r\n Golang     【输出没有进行安全转义】

fmt.Printf("%q \n", []byte("Hello, Golang")) // output: "Hello, Golang"
fmt.Printf("%q \n", "Hello, Golang")         // output: "Hello, Golang"
fmt.Printf("%q \n", `Hello \r\n World`)      // output: "Hello \\r\\n World"

fmt.Printf("%x \n", "Hello, Golang") // output: 48656c6c6f2c20476f6c616e67
fmt.Printf("%X \n", "Hello, Golang") // output: 48656C6C6F2C20476F6C616E67

打印指针

type Obj struct {
   boolean bool
   str     string
   num     int
}

func main() {
   var obj = Obj{boolean: true, str: "str", num: 27}
   fmt.Printf("%p", &obj) //0xc0000b6000
   
}

打印整型

  • %b:以二进制打印

  • %d:以十进制打印

  • %o:以八进制打印

  • %x:以十六进制打印,使用小写:a-f

  • %X:以十六进制打印,使用大写:A-F

  • %c:打印对应的的unicode码值

  • %q:该值对应的单引号括起来的go语法字符字面值,必要时会采用安全的转义表示

  • %U:该值对应的 Unicode格式:U+1234,等价于”U+%04X”

例如下面输出:

func main() {
   n := 1024

   fmt.Printf("%d 的 8 进制:%o \n", n, n)  //2000
   fmt.Printf("%d 的 10 进制:%d \n", n, n) //1024
   fmt.Printf("%d 的 16 进制:%x \n", n, n) //400

   // 将 10 进制的整型转成 16 进制打印: %x 为小写, %X 为小写
   fmt.Printf("%x \n", 1024) // 400
   fmt.Printf("%X \n", 1024) // 400

   // 根据 Unicode码值打印字符
   fmt.Printf("ASCII 编码为%d 表示的字符是: %c \n", 65, 65) // ASCII 编码为65 表示的字符是: A

   // 根据 Unicode 编码打印字符
   fmt.Printf("%c \n", 0x4E2D) // 中
   // 打印 raw 字符时
   fmt.Printf("%q \n", 0x4E2D) // '中'

   // 打印 Unicode 编码
   fmt.Printf("%U \n", '中') // U+4E2D

}

打印浮点数

  • %e:科学计数法,如-1234.456e+78

  • %E:科学计数法,如-1234.456E+78

  • %f:有小数部分但无指数部分,如123.456

  • %F:等价于%f

  • %g:根据实际情况采用%e或%f格式(以获得更简洁、准确的输出)

  • %G:根据实际情况采用%E或%F格式(以获得更简洁、准确的输出)

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
}

宽度标识符

宽度通过一个紧跟在百分号后面的十进制数指定,如果未指定宽度,则表示值时除必需之外不作填充。精度通过(可选的)宽度后跟点号后跟的十进制数指定。

如果未指定精度,会使用默认精度;如果点号后没有跟数字,表示精度为0。举例如下:

func main() {
   n := 12.34567
   fmt.Printf("%f\n", n)    // 以默认精度打印
   fmt.Printf("%9f\n", n)   // 宽度为9,默认精度
   fmt.Printf("%.2f\n", n)  // 默认宽度,精度2
   fmt.Printf("%9.2f\n", n) // 宽度9,精度2
   fmt.Printf("%9.f\n", n)  // 宽度9,精度0
}


//12.345670
//12.345670
//12.35
//    12.35
//       12

占位符:%+

  • %+v:若值为结构体,则输出将包括结构体的字段名。

  • %+q:保证只输出ASCII编码的字符,非 ASCII 字符则以unicode编码表示。

func main() {
   var obj = Obj{boolean: true, str: "string", num: 1}
   fmt.Printf("%v \n", obj)  // {true string 1}
   fmt.Printf("%+v \n", obj) // {boolean:true str:string num:1}

   // 保证只输出ASCII编码的字符
   fmt.Printf("%q \n", "golang")  // "golang"
   fmt.Printf("%+q \n", "golang") // "golang"

   // 非 ASCII 字符则以unicode编码表示
   fmt.Printf("%q \n", "中文")  // "中文"
   fmt.Printf("%+q \n", "中文") // "\u4e2d\u6587"

}

占位符:%

  • %#x:给打印出来的是 16 进制字符串加前缀 0x

  • %#q:用反引号包含,打印原始字符串

  • %#U:若是可打印的字符,则将其打印出来

  • %#p:若是打印指针的内存地址,则去掉前缀 0x

func main() {
   // 对于打印出来的是 16 进制,则加前缀 0x
   fmt.Printf("%x \n", "Hello, Golang")  // 48656c6c6f2c20476f6c616e67
   fmt.Printf("%#x \n", "Hello, Golang") // 0x48656c6c6f2c20476f6c616e67

   // 用反引号包含,打印原始字符串
   fmt.Printf("%q \n", "Hello, Golang")  // "Hello, Golang"
   fmt.Printf("%#q \n", "Hello, Golang") // `Hello, Golang`

   // 若是可打印的字符,则将其打印出来
   fmt.Printf("%U \n", '中')  // U+4E2D
   fmt.Printf("%#U \n", '中') // U+4E2D '中'

   // 若是打印指针的内存地址,则去掉前缀 0x
   a := 1024
   fmt.Printf("%p \n", &a)  // 0xc0000b2020
   fmt.Printf("%#p \n", &a) // c0000b2020

}

对齐补全

字符串

func main() {
   // 打印的值宽度为5,若不足5个字符,则在前面补空格凑足5个字符。
   fmt.Printf("a%5sc\n", "b") // output: a    bc
   // 打印的值宽度为5,若不足5个字符,则在后面补空格凑足5个字符。
   fmt.Printf("a%-5sc\n", "b") //output: ab    c

   // 不想用空格补全,还可以指定0,其他数值不可以,
   // 注意:只能在前边补全,后边补全无法指定字符。
   fmt.Printf("a%05sc\n", "b") // output: a0000bc
   // 若超过5个字符,不会截断
   fmt.Printf("a%5sd\n", "bbbccc") // output: abbbcccd
}

浮点数

func main() {
   // 保证宽度为6(包含小数点),2位小数,右对齐
   // 不足6位时,整数部分空格补全,小数部分补零,超过6位时,小数部分四舍五入
   fmt.Printf("%6.2f,%6.2f\n", 12.3, 123.4567) // 12.30,123.46

   // 保证宽度为6(包含小数点),2位小数,- 表示左对齐
   // 不足6位时,整数部分空格补全,小数部分补零,超过6位时,小数部分四舍五入
   fmt.Printf("%-6.2f,%-6.2f\n", 12.2, 123.4567) //12.20 ,123.46
}

正负号占位

如果是正数,则留一个空格,表示正数

如果是负数,则在此位置,用 - 表示

func main() {
   fmt.Printf("1% d3\n", 22) //1 223
   fmt.Printf("1% d3\n", -22)//1-223
}

三个函数对比

fmt.Print:正常打印字符串和变量,不进行格式化。不会自动换行。需要手动添加 \n 进行换行。 当相邻两者都不是字符串时,在操作数之间添加空格。

fmt.Println:正常打印字符串和变量,不会进行格式化,多个变量值之间会添加空格,并且在每个变量值后面会进行自动换行。不需要手动添加 \n进行换行。

fmt.Printf:可以按照自己需求对变量进行格式化打印。需要手动添加 \n 进行换行。

文章参考