Golang基础篇-Printf格式化

590 阅读4分钟

本文主要通过分类总结go语言中Printf格式化的多样性,方便在日常开发打印、debug、格式化等需求中即使检索出自己想要的格式化形式;文中如有描述不对或则不合理的地方,请各位大佬积极留言,我会每日及时查看并核查纠正。

值的类型

// Person 类
type Person struct {
    name, sex string
    age int
}

func test0001() {
    conk := Person{name: "conk", sex: "男", age: 20}
    // 打印值的类型
    fmt.Printf("%T\n", conk)  // main.Person
}

结构体

func test0002() {
    conk := Person{name: "conk", sex: "男", age: 20}
    // 打印结构体实例
    fmt.Printf("%v\n", conk)  // {conk 男 20}
    // 如果值是一个结构体,%+v 的格式化输出内容将包括结构体的字段名
    fmt.Printf("%+v\n", conk)  // {name:conk sex:男 age:20}
    // %#v 形式则输出这个值的 Go 语法表示。例如,值的运行源代码片段
    fmt.Printf("%#v\n", conk)  // main.Person{name:"conk", sex:"男", age:20}
}

数字类型

func test0003() {
    // 格式化整形数有多种方式,使用 %d进行标准的十进制格式化。
    fmt.Printf("%d\n", 124)  // 124
    // 输出二进制表示形式。
    fmt.Printf("%b\n", 60)  // 111100
    // 对于浮点型同样有很多的格式化选项。使用 %f 进行最基本的十进制格式化。
    fmt.Printf("%f\n", 78.9)  // 78.900000
    //%e 和 %E 将浮点型格式化为(稍微有一点不同的)科学技科学记数法表示形式。
    fmt.Printf("%e\n", 123400000.0)  // 1.234000e+08
    fmt.Printf("%E\n", 123400000.0)  // 1.234000E+08
}

布尔类型

func test0004() {
    // 格式化布尔值
    fmt.Printf("%t\n", false)  // false
}

字符串类型

func test0005() {
    // 使用 %s 进行基本的字符串输出
    fmt.Printf("%s\n", "hello")  // hello
    // 像 Go 源代码中那样带有双引号的输出
    fmt.Printf("%q\n", "hello")  // "hello"
}

字节

func test0006() {
    // 输出使用 base-16 编码的字符串,每个字节使用 2 个字符表示
    fmt.Printf("%x\n", "中")  // e4b8ad 3个字节, 一个字节2个字符
}

指针

func test0007() {
    conk := Person{name: "conk", sex: "男", age: 20}
    // 要输出一个指针的值
    fmt.Printf("%p\n", &conk)  // 0xc000062180
}

宽度精度格式化

func test0008() {
    // 当输出数字的时候,你将经常想要控制输出结果的宽度和精度,可以使用在 % 后面使用数字来控制输出宽度。默认结果使用右对齐并且通过空格来填充空白部分。
    fmt.Printf("|%-6d|\n", 123456)  // |123456|
    fmt.Printf("|%-6d|\n", 12)      // |12    |
    fmt.Printf("|%6d|\n", 12)       // |    12|  左对齐
    // 你也可以指定浮点型的输出宽度,同时也可以通过 宽度.精度 的语法来指定输出的精度。
    fmt.Printf("|%10.2f|\n", 1234567.12)    // |1234567.12|
    fmt.Printf("|%10.2f|\n", 12.1)          // |     12.10|
    fmt.Printf("|%-10.2f|\n", 12.1)         // |12.10     | 左对齐
    // 你也许也想控制字符串输出时的宽度,特别是要确保他们在类表格输出时的对齐。这是基本的右对齐宽度表示。
    fmt.Printf("|%6s|\n", "abcdef") // |abcdef|
    fmt.Printf("|%6s|\n", "foo")    // |   foo|
    fmt.Printf("|%-6s|\n", "foo")   // |foo   |  // 左对齐
}

ASCII码

func test0009() {
    // 这个输出给定整数的对应字符(ASCII码)。
    fmt.Printf("%c\n", 65)  // A
    // %x 提供十六进制编码
    fmt.Printf("%x\n", 65)  // 41
}

其他

func test0010() {
        // Sprintf 则格式化并返回一个字符串而不带任何输出。
        s := fmt.Sprintf("a %s", "string")
        fmt.Println(s)  // a string
        // 你可以使用 Fprintf 来格式化并输出到 io.Writers而不是 os.Stdout。
        fmt.Fprintf(os.Stderr, "an %s\n", "error")
}

二进制、字节、字符、unicode字符集、utf8编码规则

  • 一个字节

    • 0 00000000
    • 255 11111111
  • 一个字节可以代表256个数字(0 - 255)

  • 两个字节可以代表65535个数字(0 - 65536)

  • 字符

    • 字符编号
      • A 65 01000001
      • B 66 01000010
      • C 67 01000011
    • ASCII字符集
      • 只收录了128个字符
    • 扩展字符集
      • 只收录了256个字符
    • unicode字符集
      • 解决跨语言跨平台问题
    • 字符集促进了字符与二进制的合作
  • 案例

    • hello世界

      • 获取unicode字符集,找到其对应的编号,根据编号,找到其对应由多少个字节组成

      • 问题1-字节划分组合形成对应的字符,如何划分

      • 问题2-定长编码划分,虽然能区分字符,但是浪费内存

    • 变长编码

      • 编号 0 - 127 编码模板 0???????
      • 编号 128 - 2047 编码模板 110????? 10??????
      • 编号 2048 - 65535 编码模板 110????? 10?????? 10??????
    • 主流的utf8编码规则,即为变长编码

    • 案例回顾- 界

      • 界 的 unicode编号 30028
      • 在 编号2048 - 65535 之间,因此占用3个字节