首页 > 其他分享 >让 Go 零值变得有用

让 Go 零值变得有用

时间:2022-09-27 08:34:07浏览次数:66  
标签:string sync var 有用 func 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 程序里的许多应用场景提供了不少的便捷特性,甚至是隐晦的功能。

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

标签:string,sync,var,有用,func,Go,零值
From: https://www.cnblogs.com/cheyunhua/p/16733212.html

相关文章

  • Golang Plan9汇编研究——BP,SP和(SP)
    最近有时间研究下Golang的汇编,在开始之前,最好能了解下X86的汇编。Go汇编使用的是Plan9汇编,网上有很多资料可以查看,不过这篇我打算从自己亲手调试过的代码开始记录。Go使用......
  • Django的CBV
    https://www.bilibili.com/video/BV1z5411D7BQ?p=3&vd_source=caabcbd2a759a67e2a3de8acbaaf08ea     get、post那些方法都是固定的,只要请求使用对应的请求......
  • MongoDB Database Tools All In One
    MongoDBDatabaseToolsAllInOnehttps://www.mongodb.com/docs/database-tools/refs©xgqfrms2012-2020www.cnblogs.com/anonymous007发布文章使用:只允许注册用......
  • Hisat2+stringtie+ballgown
    Hisat2+stringtie+ballgown#加载module中的hisat2moduleloadRNAseq_hisat2在下面操作开始前,需先进性mkdir文件的创建,输入和输出的文件前面都加上了文件的绝对路径,例如:/......
  • 密码学奇妙之旅、02 混合加密系统、AES、RSA标准、Golang代码
    CTR计数器模式计数器模式CTR是分组密码模式中的一种。通过将逐次累加的计数器进行加密来生成密钥流的流密码。每次加密时会生成一个不同的值来作为计数器的初始值。可......
  • go使用JWT进行跨域认证最全教学
    JWT前言JWT是JSONWebToken的缩写。JWT本身没有定义任何技术实现,它只是定义了一种基于Token的会话管理的规则,涵盖Token需要包含的标准内容和Token的生成过程。JWT组成......
  • 【Django-rest-framework框架】第02回 APIView与序列化
    目录1.Http协议1.1简介1.2四大特性1.3请求数据格式1.4响应数据格式1.5http协议版本区别2.APIView基本使用2.1获取图书接口使用View+JsonResponsexie2.2使用APIVie......
  • golang程序健壮性相关细节
    结构体定义1、请问下面输出是什么packagemainimport("fmt")funcmain(){l:=get()fmt.Printf("%p",l)fmt.Printf("%p",l.List)for......
  • go入门之搭建环境hello word
    1.安装go #检测版本goversiongoversiongo1.18.5windows/amd642.下载goland,登陆账号没有破解的3.创建项目 4.新建go文件  5.执行文件  6.目前就......
  • golang 中 取切片元素 与 切片再生成切片的区别
    funcmain(){//定义一个切片a:=[]byte{1,2,3}fmt.Printf("a的类型%T\n",a)//a的类型[]uint8fmt.Printf("a原来的值%v\n",a)//a原来的值[1......