上一章中对于golang的语言基础说明如下:

  • 1 函数调用
  • 2 接口
  • 3 反射

接下来我们来对golang的常用关键字进行说明,主要内容有:

  • 1. for 和 range
  • 2. select
  • 3. defer
  • 4. panic 和 recover
  • 5. make 和 new

— — — — — — — — — — — — — — — — — — — — — — — — — — — —

当我们想要在 Go 语言中初始化一个结构时,可能会用到两个不同的关键字 — makenew。因为它们的功能相似,所以初学者可能会对这两个关键字的作用感到困惑1,但是它们两者能够初始化的却有较大的不同。

  • make 的作用是初始化内置的数据结构,也就是我们在前面提到的切片、哈希表和 Channel2;
  • new 的作用是根据传入的类型分配一片内存空间并返回指向这片内存空间的指针3;

我们在代码中往往都会使用如下所示的语句初始化这三类基本类型,这三个语句分别返回了不同类型的数据结构:

slice := make([]int, 0, 100)
hash := make(map[int]bool, 10)
ch := make(chan int, 5)

  1. slice 是一个包含 datacaplen 的私有结构体 internal/reflectlite.sliceHeader
  2. hash 是一个指向 runtime.hmap 结构体的指针;
  3. ch 是一个指向 runtime.hchan 结构体的指针;

相比与复杂的 make 关键字,new 的功能就很简单了,它只能接收一个类型作为参数然后返回一个指向该类型的指针:

i := new(int)var v int
i := &v

上述代码片段中的两种不同初始化方法是等价的,它们都会创建一个指向 int 零值的指针。

图 - make 和 new 初始化的类型

接下来我们将分别介绍 makenew 在初始化不同数据结构时的过程,我们会从编译期间和运行时两个不同阶段理解这两个关键字的原理,不过由于前面的章节已经详细地分析过 make 的原理,所以这里会将重点放在另一个关键字 new 上。

1. make

在前面的章节中我们已经谈到过 make 在创建切片、哈希表和 Channel 的具体过程,所以在这一小节,我们只是会简单提及 make 相关的数据结构的初始化原理。

图 - make 关键字的类型检查

在编译期间的类型检查阶段,Go 语言就将代表 make 关键字的 OMAKE 节点根据参数类型的不同转换成了 OMAKESLICEOMAKEMAPOMAKECHAN 三种不同类型的节点,这些节点会调用不同的运行时函数来初始化相应的数据结构。

2. new

编译器会在中间代码生成阶段通过以下两个函数处理该关键字:

  1. cmd/compile/internal/gc.callnew 函数会将关键字转换成 ONEWOBJ 类型的节点2;
  2. cmd/compile/internal/gc.state.expr 函数会根据申请空间的大小分两种情况处理:
    1. 如果申请的空间为 0,就会返回一个表示空指针的 zerobase 变量;
    2. 在遇到其他情况时会将关键字转换成 runtime.newobject 函数:
func callnew(t *types.Type) *Node {...n := nod(ONEWOBJ, typename(t), nil)...return n
}func (s *state) expr(n *Node) *ssa.Value {switch n.Op {case ONEWOBJ:if n.Type.Elem().Size() == 0 {return s.newValue1A(ssa.OpAddr, n.Type, zerobaseSym, s.sb)}typ := s.expr(n.Left)vv := s.rtcall(newobject, true, []*types.Type{n.Type}, typ)return vv[0]}
}

需要注意的是,无论是直接使用 new,还是使用 var 初始化变量,它们在编译器看来就是 ONEWOBJODCL 节点。这些节点在这一阶段都会被 cmd/compile/internal/gc.walkstmt 转换成通过 runtime.newobject 函数在堆上申请内存:

func walkstmt(n *Node) *Node {switch n.Op {case ODCL:v := n.Leftif v.Class() == PAUTOHEAP {if prealloc[v] == nil {prealloc[v] = callnew(v.Type)}nn := nod(OAS, v.Name.Param.Heapaddr, prealloc[v])nn.SetColas(true)nn = typecheck(nn, ctxStmt)return walkstmt(nn)}case ONEW:if n.Esc == EscNone {r := temp(n.Type.Elem())r = nod(OAS, r, nil)r = typecheck(r, ctxStmt)init.Append(r)r = nod(OADDR, r.Left, nil)r = typecheck(r, ctxExpr)n = r} else {n = callnew(n.Type.Elem())}}
}

不过这也不是绝对的,如果通过 var 或者 new 创建的变量不需要在当前作用域外生存,例如不用作为返回值返回给调用方,那么就不需要初始化在堆上。

runtime.newobject 函数会是获取传入类型占用空间的大小,调用 runtime.mallocgc 在堆上申请一片内存空间并返回指向这片内存空间的指针:

func newobject(typ *_type) unsafe.Pointer {return mallocgc(typ.size, typ, true)
}

runtime.mallocgc 函数的实现大概有 200 多行代码,我们会在后面的章节中详细分析 Go 语言的内存管理机制。

3. 小结

到了最后,简单总结一下 Go 语言中 makenew 关键字的实现原理,make 关键字的作用是创建切片、哈希表和 Channel 等内置的数据结构,而 new 的作用是为类型申请一片内存空间,并返回指向这片内存的指针。

全套教程点击下方链接直达:

IT实战:Go语言设计与实现自学教程​zhuanlan.zhihu.com

golang 切片 接口_Golang语言常用关键字之 make 和 new相关推荐

  1. golang 切片 接口_Golang简单入门教程——函数进阶使用

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是golang专题的第八篇,我们来聊聊golang当中的函数. 我们在之前的时候已经介绍过了函数的基本用法,知道了怎么样设计或者是定义一 ...

  2. golang 切片 接口_Go 经典入门系列 18:接口(一)

    点击上方蓝色"Go语言中文网"关注,每天一起学 Go 欢迎来到 Golang 系列教程[1]的第 18 个教程.接口共有两个教程,这是我们接口的第一个教程. 什么是接口? 在面向对 ...

  3. golang 切片 接口_一日看尽golang高级语法之slice

    golang系列的文章包含多篇文章,总篇如下,其中包含各篇文章的指引 明月映江雪:golang系列--个人学习笔记总篇​zhuanlan.zhihu.com 由于最近事情比较多,拖到现在才更新,另一方 ...

  4. golang 切片 接口_Go编程模式:切片,接口,时间和性能

    在本篇文章中,我会对 Go 语言编程模式的一些基本技术和要点,这样可以让你更容易掌握 Go 语言编程.其中,主要包括,数组切片的一些小坑,还有接口编程,以及时间和程序运行性能相关的话题. 本文是全系列 ...

  5. golang 切片 接口_如何理解Golang中的接口?

    个人认为,要理解 Go 的接口,一定先了解下鸭子模型. 鸭子模型 那什么鸭子模型? 鸭子模型的解释,通常会用了一个非常有趣的例子,一个东西究竟是不是鸭子,取决于它的能力.游泳起来像鸭子.叫起来也像鸭子 ...

  6. C语言的32个常用关键字

    目录 前言 一.关键字是什么? 二.关键字使用方法 1.关键字分类 2.使用方法(详解) 1.数据类型关键字 int,float,double,char short,long,signed,unsig ...

  7. golang sqlx scan 到结构体中_Golang语言并发编程之定时器

    上一章中对于golang的常用关键字说明如下: 1 for 和 range 2 select 3 defer 4 panic 和 recover 5 make 和 new 接下来我们来对golang的 ...

  8. 火龙果(redpitaya)开发板常用接口C语言开发指南(九)——产生信号脉冲(持续更新中)

    火龙果(redpitaya)开发板常用接口C语言开发指南(九)--产生信号脉冲(持续更新中) --本人为<火龙果实战指南--搭建基于Zynq处理器的测量仪器与创新实践平台>一书的作者之一, ...

  9. c语言的常用关键字和标志符号,c语言关键字及常用符号

    <c语言关键字及常用符号>由会员分享,可在线阅读,更多相关<c语言关键字及常用符号(3页珍藏版)>请在装配图网上搜索. 1.C语言关键字及常用符号32个关键字auto :声明自 ...

最新文章

  1. hdu 2433 Travel
  2. 合肥工业大学网络程序设计实验报告_【院校推荐】2020合肥工业大学计算机考研备考指导及报考分析...
  3. 1350B. Orac and Models
  4. Servlet第三篇【request和response简介、response的常见应用】
  5. python从入门到实践答案第四章_《python从入门到实践》--第四章基本操作列表 重点及课后练习...
  6. linux根据端口号找目录,Linux通过程序端口寻找程序路径
  7. 人工搜索文字不可靠,还是要使用工具
  8. paip.erlang环境搭建和脚本式escript运行halo world 在windows下attilax总结
  9. 多字节编码与Unicode码的区别 内码
  10. 飘云阁内存补丁工具使用
  11. JMP 16 全新发布,让分析更高效、更自动化
  12. 正交设计助手的使用教程(设计测试用例的工具)
  13. java reader类子类_Java之InputStreamReader类的实现
  14. 51nod 1163 最高的奖励(超级经典贪心)
  15. JavaScript介绍及其特点
  16. windows nginx出现 was not signaled for 5s
  17. html图片的隐藏与显示,Jquery中使用show()与hide()方法动画显示和隐藏图片
  18. php实训报告摘要部分怎么写,毕业论文的摘要部分怎么写(附摘要范文)
  19. mysql使用什么语句为指定_在MySQL中,可以使用_____语句来为指定数据库添加用户。...
  20. GEE:LST地表温度反演函数(针对Landsat8的T1影像和T1_L2影像集合)

热门文章

  1. 未来的C#之只读引用与结构体
  2. 使用VS Code从零开始开发调试.NET Core 1.1
  3. hibernate mysql 主从_MYSQL主从复制和写分离
  4. Android之开源视频压缩框架RxFFmpeg的commands设置
  5. LeetCode之Merge Two Sorted Lists
  6. Android之android studio如何获取证书指纹 (SHA1)
  7. C++入门指南及实战 第二步 HelloWorld及扩展详解
  8. 【C语言简单说】三:浮点数变量和字符变量(4)
  9. c 正则提取html,c – 正则表达式以获取HTML表格内容
  10. 甘肃2019年9月计算机二级报名入口,2019年9月甘肃计算机二级考试成绩查询入口...