为什么Go里值为nil可以调用函数原理分析

 更新时间:2023年08月07日 08:56:27   作者:煎鱼  
这篇文章主要为大家介绍了为什么Go里值为nil可以调用函数原理分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

起因

最近在我们 Go 的技术交流群里,有一个小伙伴提了一个程序方面的问题,还挺有意思的,分享给大家。

示例

示例程序如下:

type T struct{}
func (t *T) Hello() string {
    if t == nil {
        fmt.Println("脑子进煎鱼了")
        return ""
    }
    return "煎鱼进脑子了"
}
func main() {
    var t *T
    t.Hello()

这段程序的运行结果是什么?

从程序的分析来看,变量 t 并没有初始化,只是声明了类型。然后就直接调用了 Hello 方法,像是 nil 调用函数,理论上应该出现恐慌(panic)。

运行结果是:

panic: runtime error: invalid memory address or nil pointer dereference

对不对呢?

显然,真正的运行结果是:

脑子进煎鱼了

请你思考一下,想想这是为什么?

原理

问题的原因是:很多小伙伴认为变量 t 的值都是 nil 了,不应该还能调用到才对。

更抽象化来讲,就是 ”程序是如何检查对象指针来寻找和调度所需函数“。

实际上,在 Go 中,表达式 Expression.Name 的语法,所调用的函数完全由 Expression 的类型决定。

其调用函数的指向不是由该表达式的特定运行时值来决定,包括我们前面所提到的 nil。

具体如下:

func (p *Sometype) Somemethod (firstArg int) {}

本质上是:

func SometypeSomemethod(p *Sometype, firstArg int) {}

这么一看,其实大家应该都明白了。

上述入参 p *Sometype 是有具体上下文类型的,自然而然也就能调用到相应的方法。如果是没有任何上下文类型的,例如:nil.Somemethod 方法来调用,那肯定就是无法运行的。

与值是不是 nil,是什么,没有太多直接的影响。只要有预期类型的上下文就可以了。

总结

今天给大家分享了一个 Go 语言里面的一个小细节,平时可能很多人没注意到,毕竟 IDE 也会标黄,会避开这个问题点。

在理解 Go 的设计和思考上,我们是需要清晰其背后的原因和逻辑的,也就是类型决定其调用,而不是值(容易误判)。

以上就是为什么Go里值为nil可以调用函数原理分析的详细内容,更多关于Go值nil调用函数的资料请关注脚本之家其它相关文章!

相关文章

  • Golang Map实现赋值和扩容的示例代码

    Golang Map实现赋值和扩容的示例代码

    这篇文章主要介绍了Golang Map实现赋值和扩容的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-04-04
  • 关于golang struct 中的 slice 无法原子赋值的问题

    关于golang struct 中的 slice 无法原子赋值的问题

    这篇文章主要介绍了为什么 golang struct 中的 slice 无法原子赋值的问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2024-01-01
  • GO语言包管理工具go mod以及包详解

    GO语言包管理工具go mod以及包详解

    go mod是go的一个模块管理工具,用来代替传统的GOPATH方案,下面这篇文章主要给大家介绍了关于GO语言包管理工具go mod以及包详解的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-07-07
  • Go素数筛选分析详解

    Go素数筛选分析详解

    学习Go语言的过程中,遇到素数筛选的问题。这是一个经典的并发编程问题,是某大佬的代码,短短几行代码就实现了素数筛选,这篇文章主要介绍了Go素数筛选分析,需要的朋友可以参考下
    2022-10-10
  • Golang实现密码加密的示例详解

    Golang实现密码加密的示例详解

    数据库在存储密码时,不能明文存储,需要加密后存储,而Golang中的加密算法有很多种,下面小编就来通过简单的示例和大家简单聊聊吧
    2023-07-07
  • Go语言的连接池管理的具体使用

    Go语言的连接池管理的具体使用

    这篇文章主要介绍了Go语言的连接池管理的具体使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2026-05-05
  • golang 微服务之gRPC与Protobuf的使用

    golang 微服务之gRPC与Protobuf的使用

    这篇文章主要介绍了golang 微服务之gRPC与Protobuf的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-02-02
  • Go语言Grpc Stream的实现

    Go语言Grpc Stream的实现

    本文主要介绍了Go语言Grpc Stream的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-06-06
  • Golang实现并发安全带过期清理的缓存结构

    Golang实现并发安全带过期清理的缓存结构

    本文主要介绍了Golang实现并发安全带过期清理的缓存结构,采用RWMutex保障并发,定时清理与惰性删除处理过期,分片优化性能,应对缓存雪崩和穿透,感兴趣的可以了解一下
    2025-06-06
  • golang优先级队列的实现全过程

    golang优先级队列的实现全过程

    优先级队列是一种特殊队列,下面这篇文章主要给大家介绍了关于golang优先级队列的实现全过程,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2022-12-12

最新评论