首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

下面的两个go代码有什么不同,为什么使用了这么多不同的内存

下面的两个Go代码有什么不同,为什么使用了这么多不同的内存?

代码1:

代码语言:txt
复制
package main

import "fmt"

func main() {
    var a []int
    for i := 0; i < 1000000; i++ {
        a = append(a, i)
    }
    fmt.Println(len(a))
}

代码2:

代码语言:txt
复制
package main

import "fmt"

func main() {
    a := make([]int, 0, 1000000)
    for i := 0; i < 1000000; i++ {
        a = append(a, i)
    }
    fmt.Println(len(a))
}

这两段代码的不同之处在于内存分配的方式和内存使用情况。

代码1中,使用了切片的默认初始化方式,即var a []int,这样的切片长度为0,容量为0。在循环中通过append函数向切片中添加元素,每次添加元素时,如果切片的容量不足,会重新分配更大的内存空间,并将原有的元素复制到新的内存空间中。这种方式会导致频繁的内存分配和复制操作,消耗较多的内存和时间。

代码2中,使用了make函数初始化切片,指定了切片的长度为0,容量为1000000,即a := make([]int, 0, 1000000)。在循环中通过append函数向切片中添加元素,如果切片的容量不足,会自动扩容,但是由于初始容量已经足够,不需要频繁的内存分配和复制操作,因此效率更高,消耗的内存也较少。

综上所述,代码2使用了更少的内存,因为它避免了频繁的内存分配和复制操作。在处理大量数据时,尽量预先分配足够的内存空间,可以提高程序的性能和效率。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

Golang 是否必要内存对齐?

可见不同字段顺序,最终决定 struct 内存大小,所以有时候合理字段顺序可以减少内存开销。 这是为什么呢?因为内存对齐存在,编译器使用了内存对齐,那么最后大小结果就会不一样。...至于为什么要做对齐,主要考虑下面两个原因: 平台(移植性) 不是所有的硬件平台都能够访问任意地址上任意数据。...那么也就不难理解,为什么调整结构体内成员变量字段顺序就能达到缩小结构体占用大小疑问了,是因为巧妙地减少了 padding 存在。让它们更 “紧凑” 了。...Stats Stats } 说了这么多,但是在我们实际编码时候,多数情况都不会考虑到最优内存对齐。那有没有什么办法能自动检测当前内存布局是最优呢?答案是:有的。...^ 提示一处 struct 可以优化,来看一这个 struct 定义: type SASL struct { Enable bool Username string

1.9K31

Go每日一库之87:zap

/go.uber.org/zap QA 设计问题 为什么要在Logger性能上花费这么多精力呢?...有关为什么启用抽样更多详细信息,请参见"为什么使用示例应用日志"中启用采样. 为什么要使用示例应用程序日志? 应用程序经常会遇到错误,无论是因为错误还是因为用户使用错误。...为什么结构化日志 API 除了接受字段之外还可以接收消息? 主观上,我们发现在结构化上下文中附带一个简短描述是帮助。这在开发过程中并不关键,但它使调试和操作不熟悉系统更加容易。...要么zap安装错误,要么您引用了代码错误包名。...如果你遵循两个简单规则,就会正常工作:安装zapgo get -u go.uber.org/zap并始终导入它在你代码import "go.uber.org/zap",代码不应包含任何对github.com

42840

指针那么容易出错,为什么Go还保留?

如果你想知道为什么 Go 运行效率会那么快? 为什么程序老是报 invalid memory address or nil pointer dereference?...计算机最重要两个硬件就是 CPU 和内存吧,CPU 负责计算,内存负责临时存储数据。 我们在写代码时,定义变量在程序运行时,这些变量都被放在了内存里面,那内存是怎么存数据呢?...Go语言里面的指针 Go 里面并没完全抛弃指针,因为在很多时候指针存在,在效率上会高很多。...而在变量前面放 & 这个字符,就是取这个变量指针。 到目前为止,Go 指针核心知识点就这么多,剩下都是围绕这些在开展。...初始化时就要求分配地址就好了,比如这样: var b *int = new(int) 但是我们一般不这么写,会结合 Go 类型自动推断来处理,如下: b := new(int) 什么情况使用指针

27820

女朋友问我:小松子,你知道Go语言参数传递是传值还是传引用吗?

我们画个图来解释一什么是引用传递 学习过其他语言同学,对这个引用传递应该很熟悉,比如C++使用者,在C++中,函数参数传递方式引用传递。...改动后值是 10 所以通过输出我们可以看到,这是一个指针拷贝,因为存放这两个指针内存地址是不同,虽然指针值相同,但是是两个不同指针。...等等,好像好落下了点什么,说好go中只有值传递呢,为什么chan、map、slice类型传递却可以改变其中值呢?白着急,我们依次来验证一。 slice也是值传递吗?...说了这么多,最后再做一个总结吧,为什么slice也是值传递。之所以对于引用类型传递可以修改原内容数据,这是因为在底层默认使用该引用类型指针进行传递,但也是使用指针副本,依旧是值传递。...出个题考验你们一 欢迎在评论区留下你答案~~~ 既然你们都知道了golang只有值传递,那么这段代码来帮我分析一吧,这里值能修改成功,为什么使用append不会发生扩容?

33010

【云+社区年度征文】我是如何 3 小时上手 Golang

我在学 C 语言时候,书上和老师都说“指针就是一个地址”,但是我觉得很奇怪,“指针”既然是一个“地址”,为什么不直接了当说它是一个“地址”,而是要称呼它为“指针”。...、Go 编译器版本不同不同),因此只要在变量前使用 & 就可以得到变量地址,看下面的示意图。...通常,参数传递是进行一次内存拷贝,无论是 值传递,还是 引用传递,实时上都是进行内存拷贝,只是拷贝内容有所不同。...图片.png 从上面的示意图中可以清楚看出 main 函数中局部整型变量 i 和 test111 函数中两个参数关系,已经内存分布。...关于函数传参部分,就整理这么多。接下来开始整理一关于面向对象部分。 面向对象 面向对象几大特性,分别是 封装、继承 和 多态。

71480

go 语言程序设计》读书笔记(六)Goroutine与系统线程区别

而goroutine最大值1GB,比传统固定大小线程栈要大得多,尽管一般情况,大多goroutine都不需要这么大栈。 goroutine 调度 OS线程会被操作系统内核调度。...GOMAXPROCS Go调度器使用了一个叫做GOMAXPROCS变量来决定会有多少个操作系统线程同时执行Go代码。...其默认值是运行机器上CPU核心数,所以在一个8个核心机器上时,调度器一次会在8个OS线程上去调度GO代码。(GOMAXPROCS是前面说m:n调度中n)。...在第二次执行时,我们使用了两个操作系统线程,所以两个goroutine可以一起被执行,以同样频率交替打印0和1。...Go鼓励更为简单模式,这种模式参数对函数影响都是显式。这样不仅使程序变得更易读,而且会让我们自由地向一些给定函数分配子任务时不用担心其身份信息影响行为。

45610

18张图解密新时代内存分配器TCMalloc

(图2) 结论:FreeList里一个节点最小为8字节 备注:因为要存指针,指针大小为8字节,为什么?可以参考上篇文章《64位平台,指针自身大小为什么是8字节?》...Page概念 操作系统是按Page管理内存,本文中1Page为8KB,如下图所示: 备注:操作系统为什么按`Page`管理内存?不在本文范围。 ?...(图9) 接着,ThreadCache其实被线程持有,为什么呢? 答案:减少线程之间竞争,分配内存时减少锁过程。 这也是为什么叫`Thread Cache Alloc`原因。...解密PageHeap PageHeap主要负责管理不同规格Span,相同规格Span构成SpanList(可回顾上文SpanList概念)。 什么是相同规格Span?...Processon ---- Go轻松进阶系列 更多文章 由浅到深,入门Go语言Map实现原理 64位平台,指针自身大小为什么是8字节? ? ?

1.7K10

先聊聊「内存分配」,再聊聊Go「逃逸分析」

要搞清楚GO逃逸分析一定要先搞清楚内存分配和堆栈: 内存分配既可以分配到堆中,也可以分配到栈中。 什么数据会被分配到栈中,什么数据又会被分配到堆中呢? GO语言是如何进行内存分配呢?...其设计初衷和实现原理是什么呢? 我们先来聊一内存管理、堆、栈知识点: 内存管理 内存管理主要包括两个动作:分配与释放。逃逸分析就是服务于内存分配。...堆有时需要加锁:堆上内存,有时需要加锁防止多线程冲突 延伸知识点:为什么堆上内存有时需要加锁?而不是一直需要加锁呢?...变量大小不确定时 我们再简单修改一面的代码: package main func test() { l := 1 a := make([]int, l, l) for i := 0; i < l;...我认为没有一成不变开发模式,我们一定是在不断需求变化,业务变化中求得平衡: 举个例子 举个日常开发中函数传参例子: 有些场景我们不应该传递结构体指针,而应该直接传递结构体。 为什么会这样呢?

45710

Go中常见错误100例教程:第1章 Go易学难精

1.1.3 安全性 Go是一门静态类型语言。因此,类型检查是在编译阶段而非运行时进行。这样就保证了我们编写代码在大多数情况是类型安全。 此外,Go具有垃圾收集器来帮助开发者处理内存管理。...通过内存共享促进消息传递基本原理是什么呢? 今天,所有的CPU都有不同级别的缓存来加速对主内存(RAM)访问。跨不同线程共享变量可能会重复多次。...因此,共享内存是现代CPU提供一种错觉(我们将在并发章节深入研究这些概念)。 采用消息传递符合现代cpu构建方式,这在大多数情况对性能有重大影响。此外,她使复杂交互更容易推理。...然而,在大多数情况,我们应该支持消息传递方法,主要是因为,正如所讨论,这种方法利用了现代CPU构建方式。 消息传递是一种强大并发方法,但它不能防止数据竞争。...本书疑意在通过收集和展示Go语言各个方面的100个常见错误来帮助你成为一名熟练开发人员:基础知识、代码组织、数据和控制结构、字符串、函数和方法、错误管理、并发、测试、优化和生产。

25730

「 不懂就问 」esbuild 为什么这么快?

今天我们就来探索一: 为什么 esbuild 这么快下文主要内容: 几组性能数据对比 为什么 esbuild 这么快 esbuild upcoming roadmap esbuild 在 vite...中运用 为什么生产环境仍需打包为何vite不用 esbuild 打包?...为什么 esbuild 这么快 ? 以下几个原因。 (为了保证内容准确性, 以下内容翻译自 esbuild 官网。) 1. 它是用 Go 语言编写,并可以编译为本地代码。...每次运行打包器时,JavaScript VM 都会在没有任何优化提示情况看到打包程序代码。...这样会占用更多内存,并且会减慢速度。 Go另一个好处是它可以将内容紧凑地存储在内存中,从而使它可以使用更少内存并在CPU缓存中容纳更多内容。

1.2K10

Java VS Go 还在纠结怎么选吗,(资深后端带你深度对比)

接下来我们从多个维度对比一Go和Java, 为什么要比较它们?   ...随着越来越多后台Java应用转移到Go, 我觉得有必要来深入聊一聊这两个语言了,我们从语言层面(语言特性、速度和易用性、内存使用等方面)、社区活跃度来PK一,进而总结出这两个语言优缺点以及这两个语言开发方向...其次Java不同权限访问修饰符,为每个应用程序创建不同级别的访问权限。从 Go 1.13 开始,go 命令默认使用 Go 模块镜像和 Go 校验和数据库下载和验证模块,语言层面内置安全策略。...其实除了上面这些维度,还有很多维度,比如泛型,异常,函数式编程等语法特点,这些我们就一笔带过了,那么基于以上比较我们可以总结一两个语言优缺点: 三、优缺点总结 Go优点 代码简洁性 静态类型可编译成机器码直接运行...结论: 学 最后   终于到最后了,写完这篇文章已经是凌晨12:29了,感谢各位能看到最后,希望以上对比能给你带来一点帮助,写这么多也不容易,感谢大家看到这里,什么意见或者建议可以留言一起讨论,看到后第一时间回复

14.1K43

实战:使用rust开发动态链接库并在Golang中使用

了解Rust为什么比一些常用语言(如Golang、Java等)更适合开发通用二进制库 了解一Rust开发C-FFI库方法,并介绍一些个人实际使用中遇到问题(也可能是我太菜) 了解一Golang...中Cgo使用 很多朋友在纠结Golang和Rust选哪个,通过本次分享,加深对两个语言了解,为大家做选择多一些参考 分享目录 Get hands dirty Rust在开发二进制库上优势 为什么选择...默认情况,Rust编译器认为我们定义函数都是由Rust程序调用,这时编译器默认对函数名进行了混淆,为什么要混淆原因大家可以参考:https://internals.rust-lang.org/t...接下来还有两个函数,我们也依次来看一他们在内存使用上有什么差异。为了缩短篇幅,相同注释内容就被删除了。...因为Go垃圾回收,GoString所对应内存地址是在Go Runtime内存分配器管辖范围里,而cgo中为了实现CFFI调用,需要使用操作系统内存分配器,Go语言中这两个内存分配器对内存管理方式不一样

2.5K10

译 - 为什么要学习Go

由于每个线程消耗大约1MB内存堆大小,最终如果您开始旋转数千个线程,它们将对堆施加巨大压力,并由于内存不足而导致关闭。另外,如果您想在两个或多个线程之间进行通信,则非常困难。...另一方面,Go于2009年发布,当时多核处理器已经可用。这就是为什么是与保持并发考虑建造。Go具有goroutines而不是线程。它们从堆中消耗了将近2KB内存。...以上所有这些,使Go在处理Java,C和C ++之类并发性方面非常强大,同时保持了并发执行代码平稳性和Erlang之类美丽。 ? `Go兼顾了两个世界。...通过删除继承,Go还可轻松理解代码(因为在查看一段代码时没有要查看超类)。 没有构造函数。 没有注释。 没有泛型。 没有例外。 上述变化使Go与其他语言完全不同,并且使Go编程也与其他语言不同。...(来源:https : //github.com/golang/go/wiki/GoUsers) 结论: 尽管Go与其他面向对象语言很大不同,但它仍然是相同野兽。

56250

本立道生,Go interface背后对象模型

二哥花了不少篇幅剖析容器网络底层信息,也拿Cilium做例子介绍了CNI是什么,它是如何配合K8s完成容器网络相关配置和维护为什么要花这么多篇来介绍网络呢?...本文来聊聊这方面的内容,希望你看完后和顿悟之前一样感觉:看前咬紧笔头,困惑不已。看后恍然大悟,频频点头以示认同。同时又嘲笑自己,为何之前总是无法参透其中奥秘?...举个例子,我们知道在C++中对于class,两种data member: statci和非static,以及三种member function:static,非static和virtual,如上面的示例所示...为什么呢?引用Stanley B....我们来思考三个问题: 接口值到底是什么?它是指针吗?如果是的话,指针所指向那块内存内容是什么? any.(Stringer)这样类型断言到底是如何实现? 反射所依赖底层数据结构到底是什么

32730

go语言调度器源代码情景分析之四:函数调用栈

数据区,包括程序全局变量和静态变量(c语言静态变量,而go没有),与代码区一样,程序加载完毕后数据区大小也不会发生改变。 堆,程序运行时动态分配内存都位于堆中,这部分内存内存分配器负责管理。...值一提是传统c/c++代码就必须小心处理内存分配和释放,而在go语言中,垃圾回收器帮助我们,所以程序员只管申请内存,而不用管内存释放,这大大降低了程序员心智负担,这不光是提高了程序员生产力...,因为不同函数局部变量个数以及所占内存大小都不尽相同; 有些编译器比如gcc会把参数和返回值放在寄存器中而不是栈中,go语言中函数参数和返回值都是放在栈上; 随着程序运行,如果C、B两个函数都执行完成并返回到了...可以看到,现在D函数栈帧其实使用是之前调用B、C两个函数所使用内存,这没有问题,因为B和C函数已经执行完了,现在D函数重用了这块内存,这也是为什么在C语言中绝对不要返回函数局部变量地址,因为同一个地址内存会被重用...从上图可以看出,即使是同一个函数,每次调用都会产生一个不同栈帧,因此对于递归函数,每递归一次都会消耗一定内存,如果递归层数太多就有导致栈溢出风险,这也是为什么我们在实际开发过程中应该尽量避免使用递归函数原因之一

1.1K10

golang | 是返回struct还是返回struct指针

当我们定义一个函数时,是返回结构体呢,还是返回指向结构体指针呢? 对于这个问题,我想大部分人回答,肯定都是返回指针,因为这样可以避免结构体拷贝,使代码效率更高,性能更好。 但真的是这样吗?...写个benchmark测试: ? 执行看下结果: ? 这两个benchmark时间几乎是相等,其结果并不像我们预料那样,返回指针形式会更快些。 为什么呢?...这次结果显示,f2函数,即返回结构体形式,比f1函数,即返回指针形式,居然快了将近5倍,意不意外? 这是为什么呢? 其实在上图中,就有一些线索。...那为什么在堆上分配内存,会比在栈上分配内存这么多呢?...两点原因,一是在堆上分配内存函数runtime.newobject,其本身逻辑就比较复杂,二是堆上分配内存,后期还要通过gc来对其进行内存回收,这些逻辑加起来,远比在栈上分配内存,外加一次拷贝操作要耗时

3.5K41

Go内存分配和逃逸分析-实践总结篇

GO语言是如何进行内存分配呢?其设计初衷和实现原理是什么呢? 要搞清楚上面的问题,我们先来聊一内存管理和堆、栈知识点: 内存管理 内存管理主要包括两个动作:分配与释放。...堆有时需要加锁:堆上内存,有时需要加锁防止多线程冲突 延伸知识点:为什么堆上内存有时需要加锁?而不是一直需要加锁呢?...逃逸分析原则 Go语言虽然没有明确说明逃逸分析原则,但是以下几点准则,是可以参考。...变量大小不确定时 我们再简单修改一面的代码: package main func test() { l := 1 a := make([]int, l, l) for i := 0; i < l;...我认为没有一成不变开发模式,我们一定是在不断需求变化,业务变化中求得平衡: 举个栗子 举个日常开发中函数传参例子: 有些场景我们不应该传递结构体指针,而应该直接传递结构体。 为什么会这样呢?

40161

为不断增长Go生态系统扩展gopls

自v0.12版本发布以来,我们已经对新设计进行了微调,重点是使交互式查询(如自动完成或查找引用)速度与v0.11相比保持不变,尽管内存中保存状态要少得多。...减少内存占用和启动耗时 在深入了解详细信息之前,让我们先来看一结果!下面的图表显示了GitHub上最受欢迎28个Go存储库启动时间和内存使用情况变化。...不同编译无法完全分开:当编译一个包P时,编译器仍然需要有关P导入包提供了什么信息。为了安排这一点,Go构建系统在P本身之前编译了P导入所有包,并且Go编译器编写了每个包导出API简洁摘要。...这个改变结果是,gopls内存使用量与打开包数量及其直接导入相关。这就是为什么在上面的图表中我们观察到了次线性扩展:随着存储库变得更大,任何一个打开包所观察到项目的比例变得更小。...这两个功能都意味着当您在计算机上打开任何Go文件时,gopls都会“做正确事情”,但是在没有优化工作情况都是不可行,因为(例如)每个构建配置都会增加内存占用!

28820

Go内存分配和逃逸分析-理论篇

GO语言是如何进行内存分配呢?其设计初衷和实现原理是什么呢? 要搞清楚上面的问题,我们先来聊一内存管理和堆、栈知识点: 内存管理 内存管理主要包括两个动作:分配与释放。...堆有时需要加锁:堆上内存,有时需要加锁防止多线程冲突 延伸知识点:为什么堆上内存有时需要加锁?而不是一直需要加锁呢?...逃逸分析原则 Go语言虽然没有明确说明逃逸分析原则,但是以下几点准则,是可以参考。...变量大小不确定时 我们再简单修改一面的代码: package main func test() { l := 1 a := make([]int, l, l) for i := 0; i < l;...我认为没有一成不变开发模式,我们一定是在不断需求变化,业务变化中求得平衡: 举个栗子 举个日常开发中函数传参例子: 有些场景我们不应该传递结构体指针,而应该直接传递结构体。 为什么会这样呢?

29930
领券