Go秘密 - Interface{}: 空不是空

在本文中,我们将深入探讨interface{}类型,并全面了解它的运作方式。

让我们深入探讨。

1. 接口实际上包含两个东西,而不是一个。

在运行时,这个过程被称为“装箱”值,你可以将interface{}想象成这样:

type iface struct {
    tab  *itab
    data unsafe.Pointer
}

类型描述符tab是一个包含接口方法集、底层类型以及实现接口的底层类型的方法的小型结构体:

type itab struct {
    inter *interfacetype
    _type *_type
    hash  uint32 // copy of _type.hash. Used for type switches.
    _     [4]byte
    fun   [1]uintptr // variable sized. fun[0]==0 means _type does not implement inter.
}

interface{}变量中指针指向存储值的内存位置。

当提取一个interface{}值时,Go会通过访问类型描述符和指针来“解箱”它,然后使用这些信息创建一个适当类型的新变量。这个过程由Go运行时处理。

“你是如何了解这些秘密的呢?”

你可以通过查看Go运行时存储库了解更多信息,该存储库包含了一系列函数和数据结构,这些函数和数据结构被Go运行时系统用于管理Go程序的执行。

2. 空不是空

当一个interface{}变量持有一个nil值时,并不意味着它等于nil。下面是一个例子来说明这一点:

func main() {
    var x interface{}
    var y *int = nil
    x = y

    if x != nil {
        fmt.Println("x != nil") // actual
    } else {
        fmt.Println("x == nil") // expect
    }

    fmt.Println(x)
}

// x != nil
// <nil>

在这个例子中,我将x赋值为nil指针int值,但实际结果是"x != nil",即使当我打印x的值时,它也显示为<nil>。

这是因为当使用"=="运算符将一个interface{}变量与nil进行比较时,只有当类型描述符和值数据都为nil时才会返回true

“太荒谬了,我该怎么解决这个问题呢?”

我通常使用反射来解决这个问题,因为我不需要知道底层类型。我还会编写一个实用函数来检查nil值:

func IsAnyNil(x interface{}) bool {
     return reflect.ValueOf(x).IsNil()
}

“所以,interface(int64) = 1 和 interface(int32) = 1 不相等... 是吗?”

正如我们之前讨论的,你是正确的,类型为int64的interface{}中的值1不等于类型为int32的interface{}中的值1。为了确认这一点,我为你运行了一个测试:

func main() {
    var y int32 = 1
    var z int64 = 1

    var x1 interface{} = y
    var x2 interface{} = z

    if x1 == x2 {
        fmt.Println("x1 == x2") // expect
    } else {
        fmt.Println("x1 != x2") // actual
    }
}

// x1 != x2

总结

这就结束了我们的讨论。你现在完全理解了interface{}的工作原理,并可以自信地运用这些知识。

请记住,永远保持学习的态度,并享受其中的乐趣,愉快编码

如果你喜欢我的文章,点赞,关注,转发!

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 以下内容是我在学习和研究Go时,对Go的特性、重点和注意事项的提取、精练和总结,还有一些学习笔记(注:部分笔记是摘...
    科研者阅读 3,811评论 0 1
  • 原文:https://makeoptim.com/golang/effective-go[https://make...
    CatchZeng阅读 5,952评论 0 1
  • 开发环境 GOROOT: go的安装目录, go原生的工具在该目录下GOPATH: 通常存放自己开发的代码或第三方...
    Never_Yg阅读 2,823评论 0 0
  • 接口(interface)是一种抽象的类型,是对其他类型行为的概括和抽象。从语法角度来看,接口是一组方法签名定义的...
    JunChow520阅读 3,138评论 0 1
  • title: Go web编程学习(一)date: 2019-05-01 14:02:17tags:- study...
    Miracle778阅读 3,853评论 0 2

友情链接更多精彩内容