iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >go语言nil有哪些特性
  • 785
分享到

go语言nil有哪些特性

2023-07-05 00:07:33 785人浏览 薄情痞子
摘要

本文小编为大家详细介绍“Go语言nil有哪些特性”,内容详细,步骤清晰,细节处理妥当,希望这篇“go语言nil有哪些特性”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。nil是Go语言中一个预定义好的标识符,表示空

本文小编为大家详细介绍“Go语言nil有哪些特性”,内容详细,步骤清晰,细节处理妥当,希望这篇“go语言nil有哪些特性”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。

nil是Go语言中一个预定义好的标识符,表示空值或零值。在Go语言中,布尔类型的零值(初始值)为 false,数值类型的零值为0,字符串类型的零值为空字符串“''”,而指针、切片、映射、通道、函数和接口的零值则是nil。nil不是关键字或保留字,不同类型nil的指针是一样的,不同类型的nil是不能比较的,相同类型的nil值也可能无法比较。

nil是什么

在Go语言中,布尔类型的零值(初始值)为 false,数值类型的零值为 0,字符串类型的零值为空字符串"",而指针、切片、映射、通道、函数和接口的零值则是 nil。

nil 是Go语言中一个预定义好的标识符,有过其他编程语言开发经验的开发者也许会把 nil 看作其他语言中的 null(NULL),其实这并不是完全正确的,因为Go语言中的 nil 和其他语言中的 null 有很多不同点。

Go语言nil特性

  • nil 标识符是不能比较的

  • nil 不是关键字或保留字

  • 不同类型 nil 的指针是一样的

  • 不同类型的 nil 是不能比较的

  • 两个相同类型的 nil 值也可能无法比较

  • nil 是常见引用类型的零值

相信写过golang程序员对下面一段代码是非常非常熟悉的了:

if err != nil {    // do something....}

当出现不等于nil的时候,说明出现某些错误了,需要我们对这个错误进行一些处理,而如果等于nil说明运行正常。那什么是nil呢?查一下词典可以知道,nil的意思是无,或者是零值。零值,zero value,是不是有点熟悉?在Go语言中,如果你声明了一个变量但是没有对它进行赋值操作,那么这个变量就会有一个类型的默认零值。这是每种类型对应的零值:

bool      -> false                              numbers -> 0                                 string    -> ""      pointers -> nilslices -> nilmaps -> nilchannels -> nilfunctions -> nilinterfaces -> nil

举个例子,当你定义了一个struct:

type Person struct {  AgeYears int  Name string  Friends []Person}var p Person // Person{0, "", nil}

变量p只声明但没有赋值,所以p的所有字段都有对应的零值。那么,这个nil到底是什么呢?Go的文档中说到,nil是预定义的标识符,代表指针、通道、函数、接口、映射或切片的零值,也就是预定义好的一个变量:

type Type intvar nil Type

是不是有点惊讶?nil并不是Go的关键字之一,你甚至可以自己去改变nil的值:

var nil = errors.New("hi")

这样是完全可以编译得过的,但是最好不要这样子去做。

nil有什么用

在了解了什么是nil之后,再来说说nil有什么用。

pointers

var p *intp == nil    // true*p          // panic: invalid memory address or nil pointer dereference

指针表示指向内存的地址,如果对为nil的指针进行解引用的话就会导致panic。那么为nil的指针有什么用呢?先来看一个计算二叉树和的例子:

type tree struct {  v int  l *tree  r *tree}// first solutionfunc (t *tree) Sum() int {  sum := t.v  if t.l != nil {    sum += t.l.Sum()  }  if t.r != nil {    sum += t.r.Sum()  }  return sum}

上面的代码有两个问题,一个是代码重复:

if v != nil {  v.m()}

另一个是当tnil的时候会panic:

var t *treesum := t.Sum()   // panic: invalid memory address or nil pointer dereference

怎么解决上面的问题?我们先来看看一个指针接收器的例子:

type person struct {}func sayHi(p *person) { fmt.Println("hi") }func (p *person) sayHi() { fmt.Println("hi") }var p *personp.sayHi() // hi

对于指针对象的方法来说,就算指针的值为nil也是可以调用的,基于此,我们可以对刚刚计算二叉树和的例子进行一下改造:

func(t *tree) Sum() int {  if t == nil {    return 0  }  return t.v + t.l.Sum() + t.r.Sum()}

跟刚才的代码一对比是不是简洁了很多?对于nil指针,只需要在方法前面判断一下就ok了,无需重复判断。换成打印二叉树的值或者查找二叉树的某个值都是一样的:

func(t *tree) String() string {  if t == nil {    return ""  }  return fmt.Sprint(t.l, t.v, t.r)}// nil receivers are useful: Findfunc (t *tree) Find(v int) bool {  if t == nil {    return false  }  return t.v == v || t.l.Find(v) || t.r.Find(v)}

所以如果不是很需要的话,不要用NewX()去初始化值,而是使用它们的默认值。

slices

// nil slicesvar s []slicelen(s)  // 0cap(s)  // 0for range s  // iterates zero timess[i]  // panic: index out of range

一个为nil的slice,除了不能索引外,其他的操作都是可以的,当你需要填充值的时候可以使用append函数,slice会自动进行扩充。那么为nil的slice的底层结构是怎样的呢?根据官方的文档,slice有三个元素,分别是长度、容量、指向数组的指针:

go语言nil有哪些特性

当有元素的时候:

go语言nil有哪些特性

所以我们并不需要担心slice的大小,使用append的话slice会自动扩容。(视频中说slice自动扩容速度很快,不必担心性能问题,这个值得商榷,在确定slice大小的情况只进行一次内存分配总是好的)

map

对于Go来说,map,function,channel都是特殊的指针,指向各自特定的实现,这个我们暂时可以不用管。

// nil mapsvar m map[t]ulen(m)  // 0for range m // iterates zero timesv, ok := m[i] // zero(u), falsem[i] = x // panic: assignment to entry in nil map

对于nil的map,我们可以简单把它看成是一个只读的map,不能进行写操作,否则就会panic。那么nil的map有什么用呢?看一下这个例子:

func NewGet(url string, headers map[string]string) (*Http.Request, error) {  req, err := http.NewRequest(http.MethodGet, url, nil)  if err != nil {    return nil, err  }  for k, v := range headers {    req.Header.Set(k, v)  }  return req, nil}

对于NewGet来说,我们需要传入一个类型为map的参数,并且这个函数只是对这个参数进行读取,我们可以传入一个非空的值:

NewGet("http://google.com", map[string]string{  "USER_AGENT": "golang/gopher",},)

或者这样传:

NewGet("http://google.com", map[string]string{})

但是前面也说了,map的零值是nil,所以当header为空的时候,我们也可以直接传入一个nil

NewGet("http://google.com", nil)

是不是简洁很多?所以,把nil map作为一个只读的空的map进行读取吧。

channel

// nil channelsvar c chan t<- c      // blocks foreverc <- x    // blocks foreverclose(c)  // panic: close of nil channel

关闭一个nil的channel会导致程序panic(如何关闭channel可以看这篇文章:如何优雅地关闭Go channel)举个例子,假如现在有两个channel负责输入,一个channel负责汇总,简单的实现代码:

func merge(out chan<- int, a, b <-chan int) {  for {    select {      case v := <-a:        out <- v      case v := <- b:        out <- v    }  }}

如果在外部调用中关闭了a或者b,那么就会不断地从a或者b中读出0,这和我们想要的不一样,我们想关闭a和b后就停止汇总了,修改一下代码:

func merge(out chan<- int, a, b <-chan int) {  for a != nil || b != nil {    select {      case v, ok := <-a:          if !ok {            a = nil            fmt.Println("a is nil")            continue          }          out <- v      case v, ok := <-b:          if !ok {            b = nil            fmt.Println("b is nil")            continue          }          out <- v    }  }  fmt.Println("close out")  close(out)}

在知道channel关闭后,将channel的值设为nil,这样子就相当于将这个select case子句停用了,因为nil的channel是永远阻塞的。

interface

interface并不是一个指针,它的底层实现由两部分组成,一个是类型,一个值,也就是类似于:(Type, Value)。只有当类型和值都是nil的时候,才等于nil。看看下面的代码:

func do() error {   // error(*doError, nil)  var err *doError  return err  // nil of type *doError}func main() {  err := do()  fmt.Println(err == nil)}

输出结果是falsedo函数声明了一个*doErro的变量err,然后返回,返回值是error接口,但是这个时候的Type已经变成了:(*doError,nil),所以和nil肯定是不会相等的。所以我们在写函数的时候,不要声明具体的error变量,而是应该直接返回nil

func do() error {  return nil}

再来看看这个例子:

func do() *doError {  // nil of type *doError  return nil}func wrapDo() error { // error (*doError, nil)  return do()       // nil of type *doError}func main() {  err := wrapDo()   // error  (*doError, nil)  fmt.Println(err == nil) // false}

这里最终的输出结果也是false。为什么呢?尽管wrapDo函数返回的是error类型,但是do返回的却是*doError类型,也就是变成了(*doError,nil),自然也就和nil不相等了。因此,不要返回具体的错误类型。遵从这两条建议,才可以放心地使用if x != nil

读到这里,这篇“go语言nil有哪些特性”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注编程网精选频道。

--结束END--

本文标题: go语言nil有哪些特性

本文链接: https://www.lsjlt.com/news/348391.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • go语言nil有哪些特性
    本文小编为大家详细介绍“go语言nil有哪些特性”,内容详细,步骤清晰,细节处理妥当,希望这篇“go语言nil有哪些特性”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。nil是Go语言中一个预定义好的标识符,表示空...
    99+
    2023-07-05
  • go语言特性有哪些
    go语言特性有:1、简洁易学,降低学习门槛,尤其适合初学者;2、高效性能,能够高效地处理并发任务,从而提升程序的性能;3、并发支持,可以轻松地利用goroutine来实现并发操作,而不需要手动管理线程和锁;4、内置工具,以显著提高开发效率和...
    99+
    2023-07-31
  • go语言的最重要特性有哪些
    本文小编为大家详细介绍“go语言的最重要特性有哪些”,内容详细,步骤清晰,细节处理妥当,希望这篇“go语言的最重要特性有哪些”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。go语言最重要特性是:1、并发编程;go语...
    99+
    2023-07-04
  • Go语言中的数组有哪些特性?
    在Go语言中,数组是一种固定长度的数据结构,它由相同类型的元素组成,并按照顺序排列。在这篇文章中,我们将深入探讨数组在Go语言中的特性和用法。 数组的定义和初始化 在Go语言中,定义一个数组非常简单,只需要使用以下语法: var ar...
    99+
    2023-07-19
    关键字 框架 数组
  • C++语言有哪些特性
    本篇内容主要讲解“C++语言有哪些特性”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C++语言有哪些特性”吧!Visual C++调试技术检查代码直到头晕眼花也没有发现错误,一运行程序就死机,只...
    99+
    2023-06-17
  • Go语言的特点有哪些
    这篇文章主要讲解了“Go语言的特点有哪些”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Go语言的特点有哪些”吧!一些特点Go是静态类型的。 所有变量都需要使用给定类型声明。 bool,str...
    99+
    2023-06-16
  • php的语言特性有哪些
    这篇文章主要介绍了php的语言特性有哪些的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇php的语言特性有哪些文章都会有所收获,下面我们一起来看看吧。PHP的语言特性:1、PHP语言可以运行与多种操作系统;2、P...
    99+
    2023-06-29
  • Go语言的编写语言有哪些特点?
    Go语言是一种由Google开发的开源编程语言,于2009年正式发布。它被设计成一种简单、高效、可靠的语言,具有许多独特的特点。在本文中,我们将详细介绍Go语言的编写语言特点,并提供一...
    99+
    2024-04-02
  • C# 3.0新语言特性有哪些
    本篇内容介绍了“C# 3.0新语言特性有哪些”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!C# 3.0新语言特性和改进包括:◆自动属性(Au...
    99+
    2023-06-17
  • go语言有什么新特性
    Go语言的新特性主要集中在以下几个方面:1. 模块化支持:Go 1.11引入了Go模块的概念,可以更方便地管理和复用代码。通过go....
    99+
    2023-10-12
    Go语言
  • Go语言的特点和优势有哪些?
    Go语言的特点和优势有哪些? Go语言是一种由Google开发的编程语言,它以其简洁、快速、并发性强等特点而备受开发者的青睐。在本文中,我们将详细探讨Go语言的特点和优势,并附上一些具...
    99+
    2024-03-13
    并发 特点: 静态 强类型 优势: 性能高 go语言
  • Go 1.1有哪些新特性
    这篇文章主要讲解了“Go 1.1有哪些新特性”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Go 1.1有哪些新特性”吧!Go 1.1 介绍Go ***版(简...
    99+
    2024-04-02
  • Go 语言中 nil 切片、非 nil 切片、空切片
    php小编小新为你带来了关于Go语言中的切片类型的介绍。在Go语言中,切片有三种状态:nil切片、非nil切片和空切片。这三种切片状态在使用时具有不同的含义和特点。了解这些切片类型的区...
    99+
    2024-02-08
    go语言
  • go语言的数据类型有哪些特点
    数据类型特点有静态类型、强类型、内存安全、支持指针、丰富的数据类型、支持自定义类型、并发安全等。详细介绍:1、静态类型:Go语言是静态类型语言,变量在声明时必须指定类型,并且不能随意改变其类型;2、强类型:Go语言是强类型语言,不允许不同类...
    99+
    2023-12-14
    go语言 数据类型
  • Go语言在哪些领域有独特优势?
    Go语言在哪些领域有独特优势? Go语言是一种由Google开发的编程语言,它在不同领域拥有独特的优势,使其成为一种受欢迎的编程语言。本文将探讨Go语言在哪些领域有独特优势,并提供具体...
    99+
    2024-04-02
  • javascript语言有哪些特点
    javascript的特点:1.是一种解释型的脚本语言;2.是一种基于对象的脚本语言;3.是一种动态类型语言;4.是一种安全性语言;5.跨平台性;javascript的特点有以下几点javascript是一种解释型的脚本语言,不需要预编译,...
    99+
    2024-04-02
  • go的语言有哪些
    go的语言有基本类型、数组、切片、字典、结构体、接口、函数、通道和接收器。1、基本类型,包括布尔型、整数型、无符号整数型和浮点型等;2、数组,具有固定长度且类型一致的数据结构;3、切片,基于数组实现的,可以从已有的数组或切片中创建;4、字典...
    99+
    2023-07-31
  • python语言有哪些特点
    python语言的特点:1.是一种面向对象的编程语言,伪代码特性;2.开源;3.具有丰富强大的库;python语言具有以下几种特点:面向对象python既是面向对象的编程语言,也是一种面向对象的编程语言,python具有伪代码的特性,在开发...
    99+
    2024-04-02
  • kotlin语法特性有哪些
    这篇文章给大家分享的是有关kotlin语法特性有哪些的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。 Google I/O 2017 开发者大会中,Google 宣布正式...
    99+
    2024-04-02
  • go语言有哪些库
    go语言有fmt库、net/http库、time库、encoding/json库、database/sql库、log库、testing库、gin库、gorm库、viper库和go-crypto库。1、fmt库,提供了格式化字符串、输入输出等...
    99+
    2023-07-31
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作