Golang内存模型详解一

首页 > 脚本专栏 > Golang 更新日期: 2016-04-20
这篇文章主要介绍了Golang 内存模型详解一,本文讲解了Go内存模型interface、,需要的朋友可以参考下

开始之前

首先,这是一篇菜B写的文章,可能会有理解错误的地方,发现错误请斧正,谢谢。

为了治疗我的懒癌早期,我一次就不写得太多了,这个系列想写很久了,每次都是开了个头就没有再写。这次争取把写完,弄成一个系列。

此 nil 不等彼 nil

先声明,这个标题有标题党的嫌疑。

Go 的类型系统是比较奇葩的,nil 的含义跟其它语言有些差别,这里举个例子(可以直接进入 http://play.golang.org/p/ezFhXX0dnB 运行查看结果):

http://golang.org/doc/faq#nil_error)。

简单的说就是 nil 代表 “zero value”(空值),对于不同类型,它具体所代表的值不同。比如上面的 a 为“*A 类型的空值”,而 ai 为“interface{} 类型的空值”。造成理解失误的最大问题在于,struct pointer 到 interface 有隐式转换(var ai interface{] = a,这里有个隐式转换),至于为什么对于 Go 这种在其它转换方面要求严格,而对于 interface 要除外呢,for convenience 吧,呵呵……

碰到了这个坑,我就开始好奇了,Go 的类型系统到底是什么样的?

Go 内存模型 - interface

概述

为了读懂下面的内容,你需要:

了解 C、Go 语言

Go 1.3 源代码 (https://go.googlecode.com/archive/go1.3.zip)

PS: 由于 Go 用到了 Plan9 C 这个小众的C编译器的扩展,比如在函数签名中使用 · 字符以区分 package/function(比如runtime·panic),这对理解不会产生什么影响。

PSS: 对于 Go runtime,可以参考src/pkg/reflect(reflect包)中的的代码,对类型系统的实现的理解有帮助。

Go 语言的类型定义可以在 src/pkg/runtime/ 目录下找到,主要由以下几个文件构成:

1.runtime.h
2.type.h

对于 interface 类型,主要看下面几个结构体定义:

1.InterfaceType
2.Itab
3.Iface
4.Eface

它们的C语言定义如下 (可以在 runtime.h 中找到):

InterfaceType:

代表了总的 interface 类型,其中:

1.Type: 类型描述,所有的类型都有这个类型描述(比如 array, map, slice)
2.mhdr 以及 m: interface 接口方法列表

代码如下:

struct InterfaceType
{
    Type;
    Slice mhdr;
    IMethod m[];
};

Itab:

类似于虚函数表,该表不会被GC回收,其中:

1.inter: 指向具体的 interface 类型
2.type: 具体实现类型, 也即 receiver type
3.link: 指向下一个函数表,因为 interface 可以 embed 多个 interface,因此实现为一个链表形式
4.bad: <略>
5.unsued: <略>
6.fun: 函数列表,每个元素是一个指向具体函数实现的指针

代码如下:

struct  Itab
{
    InterfaceType*  inter;
    Type*   type;
    Itab*   link;
    int32   bad;
    int32   unused;
    void    (*fun[])(void);
};

Iface:

该类型为一般的 interface 类型所对应的数据结构,其中:

1.tab: 参见 Itab 的说明,尤其是 Itab::link
2.data: 指向具体数据(比如指向struct,当然,如果一个数据不超过一个字长,那么这个data就可以直接存放,不需要指针再做以及跳转)

代码如下:

struct Iface
{
    Itab*   tab;
    void*   data;
};

Eface:

该类型为 interface{} (empty interface) 所对应的数据结构,其中:

1.type: 具体实现类型, 也即 receiver type
2.data: 同 Iface

代码如下:

struct Eface
{
    Type*   type;
    void*   data;
};

他们的依赖关系如下图所示:

Golang内存模型详解一

先到这里,下一篇将会举例子说明给一个 interface{} 类型的变量赋值后,其具体的内存结构是怎么样的。

打了几个小时,真费时间,争取这个系列不坑 (逃


> 本站内容系网友提交或本网编辑转载,其目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如涉及作品内容、版权和其它问题,请及时与本网联系,我们将在第一时间删除内容!

相关文章
  • javascript的内存管理详解
    这篇文章介绍了javascript的内存管理详解,有需要的朋友可以参考一下介绍 低层次的语言,如C,具有低级别的内存管理命令,如:malloc()和free(),需要开发者手工释放内存.然而像javascript这样的高级语言情况则不同,对象(objects, strings 等)创建的时候分配内存,当他们不在使用的时候内存会被自动回收,这个自动回收的过程被 ...
  • 解析Android开发优化之:对Bitmap的内存优化详解
    在Android应用里,最耗费内存的就是图片资源.而且在Android系统中,读取位图Bitmap时,分给虚拟机中的图片的堆栈大小只有8M,如果超出了,就会出现OutOfMemory异常.所以,对于图片的内存优化,是Android应用开发中比较重要的内容1) 要及时回收Bitmap的内存 Bitmap类有一个方法recycle(),从方法名可以看出意思是回收 ...
  • 理解Javascript_13_执行模型详解
    在理解Javascript_12_执行模型浅析一文中,我们初步的了解了执行上下文与作用域的概念,那么这一篇将深入分析执行上下文的构建过程,了解执行上下文.函数对象.作用域三者之间的关系.函数执行环境 简单的代码: 代码如下: function say(msg,other){ var str = "nobody say:"; this.na ...
  • 详解C语言中的内存四区模型及结构体对内存的使用
    这篇文章主要介绍了C语言中的内存四区模型及结构体对内存的使用,包括结构体中内存泄漏情况的注意点提醒,需要的朋友可以参考下内存四区1.代码区代码区code,程序被操作系统加载到内存的时候,所有的可执行代码都加载到代码区,也叫代码段,这块内存是不可以在运行期间修改的.2.静态区所有的全局变量以及程序中的静态变量都存储到静态区.3.栈区栈stack是一种先进后出的 ...
  • JavaScript的内存释放问题详解
    这篇文章主要介绍了JavaScript的内存释放问题详解的相关资料,需要的朋友可以参考下本文详细的讲解了JavaScript及IE浏览器对内存的管理和释放的时机和方法,希望对前端开发人员有所帮助. 一个内存释放的实例 代码如下:<SCRIPT LANGUAGE="JavaScript"><!--strTest = &qu ...
猜你喜欢