文章插图
Go语言面试问得最多的面试题new 和 make 的区别【GO开发:GIN面试题】首先我们得知道 , Go分为数据类型分为值类型和引用类型 , 其中
值类型是 int、float、string、bool、struct和array , 它们直接存储值 , 分配栈的内存空间 , 它们被函数调用完之后会释放
引用类型是 slice、map、chan和值类型对应的指针 它们存储是一个地址(或者理解为指针),指针指向内存中真正存储数据的首地址 , 内存通常在堆分配 , 通过GC回收
区别new 的参数要求传入一个类型 , 而不是一个值 , 它会申请该类型的内存大小空间 , 并初始化为对应的零值 , 返回该指向类型空间的一个指针
make 也用于内存分配 , 但它只用于引用对象 slice、map、channel的内存创建 , 返回的类型是类型本身
值传递和指针传递有什么区别值传递:会创建一个新的副本并将其传递给所调用函数或方法 指针传递:将创建相同内存地址的新副本
需要改变传入参数本身的时候用指针传递 , 否则值传递
另外 , 如果函数内部返回指针 , 会发生内存逃逸
聊聊内存逃逸分析Go的逃逸分析是一种确定指针动态范围的方法 , 可以分析程序在哪些可以访问到指针 , 它涉及到指针分析和状态分析 。
当一个变量(或对象)在子程序中被分配时 , 一个指向变量的指针可能逃逸到其它程序 , 或者去调用子程序 。 如果使用尾递归优化(通常函数式编程是需要的) , 对象也可能逃逸到被调用程序中 。如果一个子程序分配一个对象并返回一个该对象的指针 , 该对象可能在程序中的任何一个地方都可以访问 。
如果指针存储在全局变量或者其它数据结构中 , 它们也可能发生逃逸 , 这种情况就是当前程序的指针逃逸 。逃逸分析需要确定指针所有可以存储的地方 , 保证指针的生命周期只在当前进程或线程中 。
导致内存逃逸的情况比较多(有些可能官方未能够实现精确的逃逸分析情况的bug) , 通常来讲就是如果变量的作用域不会扩大并且行为或者大小能够在其编译时确定 , 一般情况下都分配栈上 , 否则就可能发生内存逃逸到堆上 。
引用内存逃逸的典型情况: * 在函数内部返回把局部变量指针返回 局部变量原本应该在栈中分配 , 在栈中回收 。但是由于返回时被外部引用 , 因此生命周期大于栈 , 则溢出
- 发送指针或带有指针的值到channel中 在编译时 , 是没办法知道哪个 goroutine 会在 channel上接受数据 , 所以编译器没办法知道变量什么时候释放 。
- 在一个切片上存储指针或带指针的值 一个典型的例子就是 []*string , 这会导致切片的内容逃逸 , 尽管其后面的数组在栈上分配 , 但其引用值一定是在堆上
- slice 的背后数组被重新分配了 因为 Append 时可能会超出其容量( cap ) 。slice 初始化的地方在编译时是可以知道的 , 它最开始会在栈上分配 。如果切片背后的存储要基于运行时的数据进行扩充 , 就会在堆上分配 。
- 在 interface 类型上调用方法 在 interface 类型上调用方法都是动态调度的 —— 方法的真正实现只能在运行时知道 。想像一个 io.Reader 类型的变量 r , 调用 r.Read(b) 会使得 r 的值和切片b 的背后存储都逃逸掉 , 所以会在堆上分配 。
作为一个内存池 , 它的基本部分包括以下几部分:
- 首先 , 它会想操作系统申请大块内存 , 自己管理这部分内存
- 然后 , 它是一个池子 , 当上层释放内存时它不实际归还给操作系统 , 而是放回池子重复利用
- 接着 , 内存管理中必然会考虑的就是内存碎片问题 , 如果尽量避免内存碎片 , 提高内存利用率 , 像操作系统中的首次适应 , 最佳适应 , 最差适应 , 伙伴算法都是一些相关的知识背景 。
推荐阅读
- Tauri:下一代桌面应用开发框架?
- |吴君如夫妇刘嘉玲夫妇聚餐!4人紧贴肩膀比心,兴奋大笑场面欢快
- 敷面膜鼻子周围刺痛的原因有哪些
- 鼻子侧面长硬块按压痛怎么办
- 李连杰|李连杰借5000w帮利智还债,开公司后,小伙面试说能隔空打倒门板
- |职场里面最常见的几件事:与同事相处,需要做到三思而后行
- 李易峰|曝李易峰变卖北京千万豪宅!东南亚公司出高价签他,从此改头换面
- 权志龙|韩版ELLE创刊30周年,集齐六大封面人物,权志龙Jennie另类“合体”
- |章泽天父亲露面,在女婿东哥面前显得有些拘谨,一家人十分幸福
- |妈妈卢靖姗则一边抱着宝宝一边亲吻老公脸颊,画面幸福温馨十足