您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > Go语言

Go 语言 Malloc 的惯用语法

时间:2019-09-23 13:31:31  来源:  作者:

 

我终于又开始使用 Go 语言编程了。虽然我在前两年多的时间里积极参与这个项目,但从 2012 年起,我就基本没有参加过这个项目。最初,我之所以做出贡献,是因为我是贝尔实验室 Plan 9(操作系统) 和 FreeBSD 的粉丝。我喜欢可用的、基于 csp 的语言,但是 Go 最初的版本只能在 linux 和 OS X 上运行。那时候我只有 FreeBSD 系统,因此,我将编译器工具链、运行时和标准库移植到 FreeBSD (有很多调试成果来自 Russ Cox)。

然而,过去我的大部分工作都是在低延迟的系统软件上,它们大部分是用 C 语言编写的,自2007年起,我所有的雇主都不再支持 FreeBSD。因为我并没有真正的机会用 Go 语言去编写新的软件,而且我最终也不再对维护一个操作系统的知识感兴趣,我只是为了好玩,所以我对 Go 语言的使用和贡献都被搁置了。

现在我在谷歌工作,我终于有机会用 Go 语言写代码了。虽然我仍然喜欢这门语言,但有一些经验报告,例如风格那样的东西结果阻止了我在过去的 5~6 年里使用这门语言,而我现在觉得有些麻烦。在一些同事的建议下,我想我应该至少记录下其中的一个。

我想念的一件事情是 C 语言 malloc 那样的习惯用法。在 C 语言中,分配的内存通常是对 mallocs -family 函数的调用,它至少给您足够的内存来完成您想要的功能,或者并不给您分配内存。惯用语法大致是这样的:

Go 语言 Malloc 的惯用语法

 

注意,p (T *) 的类型只出现一次。这一行代码利用了它的操作数时的大小,并且显示了一个指针 —— 这其实是没有发生的事情,因为操作符 sizeof 的结果必须①在编译时是可识别的。这种编程语言而不是语法定义的结果是 sizeof 产生了指向对象的大小;它不会变成运行时的东西。C 语言的好处是,如果我改变用 T 表示的类型,我只改变声明或定义中的类型。在 site(s) 中不需要做任何更改,指针对象被分配给内存分配的结果。上面的示例很简单,让我们考虑一个更复杂的情况,结构成员指向某种类型:

Go 语言 Malloc 的惯用语法

 

如果以后我们想要更改 struct set 来支持除 int 以外的成员,我们可能会将成员更改为一个union,并添加一些 enum 类型来指定一些我们想要添加的字段。我们可以在不改变 set_create 中的任何代码的情况下做到这一点。

每次我使用 Go 语言创建了一些结构类型,当需要嵌入一些像 slice 和 map 那样需要分配内存的字段的时候都让我很抓狂。在 Go 中,我们被迫重复表达我们想要分配的东西的类型,尽管编译器熟知这种类型而且类型推断是符合语言习惯的(试想一下如这样的表达式 a:= b ),我有时不得不深究一下嵌入字段的类型是什么。让我们来看看在创建一个嵌入了 map 的结构体所涉及的内容:

Go 语言 Malloc 的惯用语法

 

我们还可以在 NewNamedMap 中使用 make ,但是仍然保留了return &NamedMap{name: name, m: make(map[string]string)} — 再次,重复它的类型。经过深思熟虑的代码,应该只有一个(额外的)地方需要我们指定类型来分配它,但是当类型改变时,这仍然需要多处改动代码。当我在做原型的时候,这就会让我抓狂,而且我还没有充分考虑到我需要保存在 map 中的状态。我发现在很多地方需要自己手动将 map[string]string 更改为 map[string]T,每次我需要更改多行代码时,它都会使我感到困扰。

有人可能会说,在写代码之前,我应该多考虑一下我需要什么,那样会更好。但我仍然会反驳说,在项目的生命周期中开发额外的状态需求并不少见,比如在上面的例子中。随着时间的推移,系统的约束也可能会发生变化,这样一种最初非常好的类型最终会变得不可用。在 Go 中,set 结构可能是这样的:

Go 语言 Malloc 的惯用语法

 

你可能会问为什么我不只是用一个 slice,答案是这是一个演示这个问题的简单例子。不管怎样,我们以后可能想要支持不同类型的 slice,那样我们又遇到了之前的问题。set 中如果有一个 slice,我们可能可以忽略初始化,假设我们在添加后只从 slice 中读取。由于形如 map 和 channel 那样的类型,因为我们必须在使用前进行分配,所以会使得情况更加复杂。那么在某个地方重复输入信息并不罕见。

我不知道该如何解决这个问题。对于复合文本,可能可以添加如下语法:

Go 语言 Malloc 的惯用语法

 

如果你有一个指向 slice 的指针:

Go 语言 Malloc 的惯用语法

 

我不知道我是否喜欢这些复合文字语法。在 C 语言中,为支持 sizeof 行为而进行的修正感觉更有表现力和明显:

Go 语言 Malloc 的惯用语法

 

但也许这只是我用 C 语言编程的时间太长了。

我不知道改变新的有相似的行为是有用的还是有价值的;我怀疑它的使用是不寻常的。在任何情况下,我都清楚这将减少重构软件以及编写新的软件的开销。

这个问题并不是那么糟糕,但修复它肯定会让我觉得更好。在很多情况下,Go已经比 C 和 C++ (我至今无法忍受) 更有表现力了。我认为,如果在语言中添加了对分配类型的推断的支持,那么 Go 语言对 C 系统程序员来说就会更有吸引力,因为除了 GC ,他们还有其他坚持的理由。(就我个人而言,我还希望看到一个关于支持系统级并发的更好的事情,但最好是单独发布。)

我编辑了这篇文章,以修复 C 示例中的一个错误。当我最初编写这个示例时,struct set 没有使用灵活的数组成员。Anmol Sethi 写信询问这个特性,并指出我错误地分配和再次分配给了FAM。我忘记了要删除那些代码。

注释:

① : Kate Flavel 提醒我,对于 VLA 类型来说,这不是必须的,因为它是如此的无用,我总是忘记这点。这种类型有它自己的表达式求值。


via: https://9vx.org/post/a-malloc-idiom-in-go/

作者:Devon 译者:SergeyChang 校对:polaris1119

本文由 GCTT 原创编译,Go语言中文网 荣誉推出



Tags:Go Malloc   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
Go 语言 Malloc 的惯用语法
我终于又开始使用 Go 语言编程了。虽然我在前两年多的时间里积极参与这个项目,但从 2012 年起,我就基本没有参加过这个项目。最初,我之所以做出贡献,是因为我是贝尔实验室 Plan...【详细内容】
2019-09-23  Search: Go Malloc  点击:(722)  评论:(0)  加入收藏
▌简易百科推荐
宝藏级Go语言开源项目——教你自己动手开发互联网搜索引擎
DIYSearchEngine 是一个能够高速采集海量互联网数据的开源搜索引擎,采用 Go 语言开发。Github 地址:https://github.com/johnlui/DIYSearchEngine运行方法首先,给自己准备一杯...【详细内容】
2024-03-12  OSC开源社区    Tags:Go语言   点击:(29)  评论:(0)  加入收藏
Go Gin框架实现优雅地重启和停止
在Web应用程序中,有时候我们需要重启或停止服务器,无论是因为更新代码还是进行例行维护。在这种情景下,我们需要保证应用程序的可用性和数据的一致性。这就需要优雅地关闭和重...【详细内容】
2024-01-30  源自开发者  微信公众号  Tags:Go   点击:(70)  评论:(0)  加入收藏
如何让Go程序以后台进程或daemon方式运行
本文探讨了如何通过Go代码实现在后台运行的程序。最近我用Go语言开发了一个WebSocket服务,我希望它能在后台运行,并在异常退出时自动重新启动。我的整体思路是将程序转为后台...【详细内容】
2024-01-26  Go语言圈  微信公众号  Tags:Go程序   点击:(61)  评论:(0)  加入收藏
深入Go底层原理,重写Redis中间件实战
Go语言以其简洁、高效和并发性能而闻名,深入了解其底层原理可以帮助我们更好地利用其优势。在本文中,我们将探讨如何深入Go底层原理,以及如何利用这些知识重新实现一个简单的Re...【详细内容】
2024-01-25  547蓝色星球    Tags:Go   点击:(74)  评论:(0)  加入收藏
Go 内存优化与垃圾收集
Go提供了自动化的内存管理机制,但在某些情况下需要更精细的微调从而避免发生OOM错误。本文将讨论Go的垃圾收集器、应用程序内存优化以及如何防止OOM(Out-Of-Memory)错误。Go...【详细内容】
2024-01-15  DeepNoMind  微信公众号  Tags:Go   点击:(64)  评论:(0)  加入收藏
Go函数指针是如何让你的程序变慢的?
导读Go 语言的常规优化手段无需赘述,相信大家也能找到大量的经典教程。但基于 Go 的函数值问题,业界还没有太多深度讨论的内容分享。本文作者根据自己对 Go 代码的使用与调优...【详细内容】
2024-01-15  腾讯云开发者  微信公众号  Tags:Go函数   点击:(91)  评论:(0)  加入收藏
Go编程中调用外部命令的几种场景
在很多场合, 使用Go语言需要调用外部命令来完成一些特定的任务, 例如: 使用Go语言调用Linux命令来获取执行的结果,又或者调用第三方程序执行来完成额外的任务。在go的标准库...【详细内容】
2024-01-09  suntiger    Tags:Go编程   点击:(116)  评论:(0)  加入收藏
Go 语言不支持并发读写 Map,为什么?
Go语言的map类型不支持并发读写的主要原因是并发读写会导致数据竞态(data race),这意味着多个 goroutine 可能同时访问并修改同一个 map,从而引发不确定的结果。在Go语言的设计...【详细内容】
2024-01-05  Go语言圈  微信公众号  Tags:Go 语言   点击:(83)  评论:(0)  加入收藏
Go微服务入门到容器化实践
Go微服务入门到容器化实践Go 是一门高效、现代化、快速增长的编程语言,非常适合构建 Web 应用程序。而 Docker 是一种轻量级的容器化技术,能够使得您的应用程序在任何地方运行...【详细内容】
2024-01-01  大雷家吃饭    Tags:Go微服务   点击:(69)  评论:(0)  加入收藏
你是否想知道如何应对高并发?Go语言为你提供了答案!
并发编程是当前软件领域中不可忽视的一个关键概念。随着CPU等硬件的不断发展,我们都渴望让我们的程序运行速度更快、更快。而Go语言在语言层面天生支持并发,充分利用现代CPU的...【详细内容】
2023-12-29  灵墨AI探索室  微信公众号  Tags:Go语言   点击:(114)  评论:(0)  加入收藏
站内最新
站内热门
站内头条