如果你看过 Go 语言标准库,应该有见到过,有一些函数只有签名,没有函数体。你有没有感觉到很奇怪?这到底是怎么回事?我们自己可以这么做吗?本文就来解密它。

首先,函数肯定得有实现,没有函数体,一定是在其他某个地方。Go 中一般有两种形式。

函数签名使用Go,然后通过该包中的汇编文件来实现它

比如,在标准库 sync/atomic 包中的函数基本只有函数签名。比如:atomic.StoreInt32

// StoreInt32 atomically stores val into *addr.
func StoreInt32(addr *int32, val int32)

它的函数实现在哪呢?其实只要稍微留意一下发现该目录下有一个文件:asm.s,它提供了具体的实现,即通过汇编来实现:

TEXT ·StoreInt32(SB),NOSPLIT,$0
JMP runtime∕internal∕atomic·Store(SB)

具体的实现,在 runtime∕internal 文件夹中,有兴趣你可以打开 asm_amd64.s 看看。

很明显,这种方式一方面会是效率的考虑,另一方面,有一些代码只能汇编实现。

以上方式,你自己也可以尝试。比如实现一个 Sum(a, b int) int。欢迎评论给出你的代码。

通过//go:linkname指令来实现

比如,在标准库 time 包中的 Sleep 函数:

// Sleep pauses the current goroutine for at least the duration d.
// A negative or zero duration causes Sleep to return immediately.
func Sleep(d Duration)

它的实现在哪里呢?在 time 包中并没有找到相应的汇编文件。

按照 Go 源码的风格,这时候一般需要去 runtime 包中找。我们会找到 time.go,其中有一个函数:

// timeSleep puts the current goroutine to sleep for at least ns nanoseconds.
//go:linkname timeSleep time.Sleep
func timeSleep(ns int64) {
...
}

这就是我们要找的 time.Sleep 的实现。

如果你有认真跟着学习「每日一学」,对于 //go:linkname 应该不陌生,这里的关键就在于这个指令,它的格式是:

//go:linkname 函数名 包名.函数名

因此我们在遇到函数没有实现,但汇编又不存在时,可以通过尝试搜索:go:linkname xxx xx.xxx 的形式来找,比如 time.Sleep 就可以通过 //go:linkname timeSleep time.Sleep 来查找具体实现在哪。

这里面要提示一点,使用 //go:linkname,必须导入 unsafe 包,所以,有时候会见到:import _ "unsafe" 这样的代码。

一般来说,我们自己的代码不会使用这样的方式,但你会写一个示例试试吗?欢迎评论给出你的代码。

另外,想想为什么 time.Sleep 的实现要这么搞?

转载自:

为什么 Go 标准库中有些函数只有签名,没有函数体?

为什么 Go 标准库中有些函数只有签名,没有函数体?的更多相关文章

  1. golang标准库中有些函数只有签名没有函数体是怎么回事?

  2. 彻底弄清c标准库中string.h里的常用函数用法

    在我们平常写的c/c++程序,一些算法题中,我们常常会用到c标准库中string.h文件中的函数,这些函数主要用于处理内存,字符串相关操作,是很有用的工具函数.而且有些时候,在笔试或面试中也会出现让你 ...

  3. STL笔记(6)标准库:标准库中的排序算法

    STL笔记(6)标准库:标准库中的排序算法 标准库:标准库中的排序算法The Standard Librarian: Sorting in the Standard Library Matthew A ...

  4. python标准库总的random函数用法

    Python标准库中的random函数,可以生成随机浮点数.整数.字符串,甚至帮助你随机选择列表序列中的一个元素,打乱一组数据等.random中的一些重要函数的用法:1 ).random() 返回0& ...

  5. Python 标准库中的装饰器

    题目描述 1.简单举例 Python 标准库中的装饰器 2.说说你用过的 Python 标准库中的装饰器 1. 首先,我们比较熟悉,也是比较常用的 Python 标准库提供的装饰器有:property ...

  6. c/c++标准库中的文件操作总结

    1 stdio.h是c标准库中的标准输入输出库 2 在c++中调用的方法 直接调用即可,但是最好在函数名前面加上::,以示区分类的内部函数和c标准库函数. 3 c标准输入输出库的使用 3.1 核心结构 ...

  7. C标准库中atoi的一种可能的实现

    为避免与标准库中的atoi产生歧义, 我将自己编写的函数命名为strToInt, 以下是示例代码 #include <stdio.h> int strToInt(const char *s ...

  8. 标准库中的装饰器 lru_cache和全新的 singledispatch

    Python 内置了三个用于装饰方法的函数:property.classmethod 和 staticmethod. 另一个常见的装饰器是 functools.wraps,它的作用是协助构建行为 良好 ...

  9. 用CAS操作实现Go标准库中的Once

    Go标准库中提供了Sync.Once来实现"只执行一次"的功能.学习了一下源代码,里面用的是经典的双重检查的模式: // Once is an object that will p ...

随机推荐

  1. [译]C# 7系列,Part 7: ref Returns ref返回结果

    原文:https://blogs.msdn.microsoft.com/mazhou/2017/12/12/c-7-series-part-7-ref-returns/ 背景 有两种方法可以将一个值传 ...

  2. STM32的Keil找不到想要flash的解决方法

    STM32的Keil找不到想要flash的解决方法:https://blog.csdn.net/qq_38376586/article/details/79582020

  3. 从eslint规则学点JavaScript知识

    在知识星球陆续发了些eslint小知识,意在通过eslint知识去了解规则内部的原理,汇总在此: prefer-const 含义:始终用const定义你从不修改的变量,如果会被修改则使用let,永不使 ...

  4. 搭建私人的云笔记_使用webdav服务

    搭建私人的云笔记_使用webdav服务 转载注明来源: 本文链接 来自osnosn的博客,写于 2019-10-10. 手机上有很多云笔记app,大多支持云存储.可是把笔记放在别人的服务器上,总觉得不 ...

  5. Kafka实战(七) - 优雅地部署 Kafka 集群

    既然是集群,必然有多个Kafka节点,只有单节点构成的Kafka伪集群只能用于日常测试,不可能满足线上生产需求. 真正的线上环境需要考量各种因素,结合自身的业务需求而制定.看一些考虑因素(以下顺序,可 ...

  6. android:Program type already present: android.support.v4.app.INotificationSideChannel

    背景 这个错误的原因是:androidx和 android.support同时存在. 首先,网上有很多解答说这样处理: 在 gradle.properties 添加: android.useAndro ...

  7. JavaBean动态添加删除属性

    1.cglib BeanGenerator beanGenerator = new BeanGenerator(); beanGenerator.addProperty("id", ...

  8. xml-mapping xml 与 java 对象转换映射框架,像 XStream 一样优雅地读写xml

    xml xml 是 java 实现的 xml 框架. 希望以最优雅的方式进行 xml 和 java 之间的转换处理,一行代码搞定一切. 特点 对象的和 xml 的互相映射 支持注解 @Alias 指定 ...

  9. Spring Security OAuth2 开发指南(非最新版本)

    请注意哈,本文翻译的时候,官网的的版本和本文翻译的时候是一一对应的. 但是官网已经更新文档和概念了,因此和本文翻译的就不在是同一个范围了. 因此我已经将标题修改为(非最新版本),各位老铁直接看官网就可 ...

  10. C#/.Net开发入门篇(2)——第一个控制台应用程序

    相信看了上一篇文章的小伙伴已经安装好自己的开发工具了VS了,这一篇文章就教大家怎么创建第一个应用程序. 下面大家跟着我的操作一起来创建自己的第一个应用程序吧 一.打开VS工具点击左上角的文件→新建→项 ...