• 让 Go 零值变得有用


    大家好,我是煎鱼。

    前文给大家分享了《10+ 条 Go 官方谚语,你知道几条?》,今天进一步讲讲第 5 条谚语 Make the zero value useful(让零值变得有用),看看里面讲的是什么意思。

    背景

    Go 语言中有一个有些特殊的概念,叫做零值。许多转语言的同学经常会弄混淆,一开始会不适应。

    代码如下:

    func main() {
     var i int
     var f float64
     var b bool
     var s string
     fmt.Printf("%v %v %v %q\n", i, f, b, s)
    }

    输出结果:

    0 0 false ""

    这会导致大家在定义各种数据库字段时比较纠结,又会说 Go 这零值,例如:整型的零值 0,跟数据库里的 0 枚举值冲突。又或是做入参判断时怎么区别开?

    一时半会想不明白,为什么 Go 要定义这个零值来增加复杂度?

    有什么用

    官方诠释

    Go 核心团队的 @Dave Cheney 在《What is the zero value, and why is it useful?[1]》中对零值进行了详细的阐释,以下部分为该文的展开介绍。

    将一个值设置为已知默认值的特性,对于程序的安全性和正确性非常重要。可以使你的 Go 程序更加简单和紧凑。这就是 Go 程序员常说的 "给你的结构一个有用的零值"。

    官方案例

    以下是 Go 官方给出的几个零值的例子,非常具有代表性。分别是:

    • sync.Mutex。
    • byte.Buffer。
    • slices。
    • nil func。

    Sync.Mutex

    sync.Mutex 被设计为无需显式初始化就可以使用,可以实现这个功能的原因是 sync.Mutex 包 含两个未导出的整数字段。

    用大白话讲,就是由于零值的存在,只要声明了 sync.Mutex,这些字段就会被设置为 0(值会被初始化)。

    因此可以无需显式初始化就可以开箱即用

    如下代码:

    package main

    import "sync"

    type MyInt struct {
            mu sync.Mutex
            val int
    }

    func main() {
            var i MyInt

            // i.mu is usable without explicit initialisation.
            i.mu.Lock()
            i.val++
            i.mu.Unlock()
    }

    Byte.Buffer

    因为有零值的存在,bytes.Buffer 在进行写入或读取的操作时,不需要人为的进行明确的初始化。也能做到很好的开箱即用。

    如下代码:

    package main

    import "bytes"
    import "io"
    import "os"

    func main() {
            var b bytes.Buffer
            b.Write([]byte("Hello world"))
            io.Copy(os.Stdout, &b)
    }

    注:io.Copy 需要一个 io.Reader 作为它的第二个参数,所以我们需要传递一个指向 b 的指针。

    Slices

    在 slices 的定义中,它的零值是 nil。这意味着你不需要显式定义一个 slices,只需要直接声明它,就可以使用了。

    如下

    package main

    import "fmt"
    import "strings"

    func main() {
            // s := make([]string, 0)
            // s := []string{}
            var s []string

            s = append(s, "Hello")
            s = append(s, "world")
            fmt.Println(strings.Join(s, " "))
    }

    Nil func

    你可以在有 nil 值的类型上调用方法,这也是零值作为缺省值的作用之一。

    这个场景,甚至一度让许多 Go 程序员以为是 BUG,我还专门写过文章。这是可行的,其实是零值的延伸出来的用法。

    如下代码:

    package main

    import "fmt"

    type Config struct {
            path string
    }

    func (c *Config) Path() string {
            if c == nil {
                    return "/usr/home"
            }
            return c.path
    }

    func main() {
            var c1 *Config
            var c2 = &Config{
                    path: "/export",
            }
            fmt.Println(c1.Path(), c2.Path())
    }

    总结

    零值,在 Go 里虽然是一个缺省值。但它本质上不仅仅是一个 “缺省”,它还在 Go 程序里的许多应用场景提供了不少的便捷特性,甚至是隐晦的功能。

    希望本文对你对零值的理解有进一步的帮助!

  • 相关阅读:
    EasyUI学习笔记之panel
    下载百度上的图片C#——输入名字就可以下载
    【转--- 数据挖掘的心得学习】
    美团推荐算法实践
    spring零配置AOP踩坑指南
    Spring学习笔记(一)
    工具类--生成随机姓名及指定长度随机字符串
    Mybatis中文模糊查询,数据库中有数据,但无结果匹配
    mybatis笔记
    code forces Watermelon
  • 原文地址:https://www.cnblogs.com/cheyunhua/p/16733212.html
Copyright © 2020-2023  润新知