脚本之家,脚本语言编程技术及教程分享平台!
分类导航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服务器之家 - 脚本之家 - Golang - Go 的零值有什么用?看看这四个场景

Go 的零值有什么用?看看这四个场景

2022-09-01 17:08脑子进煎鱼了陈煎鱼 Golang

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

背景

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 程序里的许多应用场景提供了不少的便捷特性,甚至是隐晦的功能。

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

原文地址:https://mp.weixin.qq.com/s/Ucqqg4h9uRo7RVd8XCz80w

延伸 · 阅读

精彩推荐
  • Golang成功安装vscode中go的相关插件(详细教程)

    成功安装vscode中go的相关插件(详细教程)

    这篇文章主要介绍了成功安装vscode中go的相关插件的详细教程,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以...

    Leo_wlCnBlogs3362020-07-05
  • GolangGo语言struct类型介绍

    Go语言struct类型介绍

    这篇文章主要介绍了Go语言struct类型介绍,本文讲解了struct的2种声明方式,struct的匿名字段等内容,需要的朋友可以参考下 ...

    junjie4442020-04-12
  • Golanggolang针对map的判断,删除操作示例

    golang针对map的判断,删除操作示例

    这篇文章主要介绍了golang针对map的判断,删除操作,结合具体实例形式分析了Go语言map判断与删除相关操作技巧,需要的朋友可以参考下 ...

    newjueqi2942020-05-06
  • Golanggo install/build生成的文件命名和路径操作

    go install/build生成的文件命名和路径操作

    这篇文章主要介绍了go install/build生成的文件命名和路径操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    seafooler20412021-02-23
  • Golanggolang包快速生成base64验证码的方法

    golang包快速生成base64验证码的方法

    这篇文章主要介绍了golang包快速生成base64验证码的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友...

    林台山人9552020-06-07
  • GolangGo语言中的range用法实例分析

    Go语言中的range用法实例分析

    这篇文章主要介绍了Go语言中的range用法,实例分析了range的功能与使用技巧,具有一定参考借鉴价值,需要的朋友可以参考下 ...

    不是JS3702020-04-17
  • Golanggo语言中的defer关键字

    go语言中的defer关键字

    这篇文章介绍了go语言中的defer关键字,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...

    taadis6562022-07-29
  • Golanggo语言使用pipe读取子进程标准输出的方法

    go语言使用pipe读取子进程标准输出的方法

    这篇文章主要介绍了go语言使用pipe读取子进程标准输出的方法,实例分析了Go语言针对进程操作的技巧,具有一定参考借鉴价值,需要的朋友可以参考下 ...

    令狐不聪3762020-04-24