• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

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

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

如果你看过 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 标准库中有些函数只有签名,没有函数体?

 

转 https://www.cnblogs.com/itbsl/p/11410857.html


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
Go语言实现TCP通信发布时间:2022-07-10
下一篇:
在windows系统下打包linux平台运行的go程序发布时间:2022-07-10
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap