go语言魔法技能go:linkname

我们在看Go语言的源码时,经常会看到一些特别的注释,比如:

//go:build
//go:linkname
//go:nosplit
//go:noescape
//go:uintptrescapes
//go:noinline
//go:nowritebarrierrec

等等,这些特别的注释其实是Go编译器的指示指令。这里介绍一下go:linkname指令其及用法,并给出各种用法的完整实例,网上很少有各种用法的完整实例的。

go:linkname的指令格式为:

//go:linkname localname [importpath.name]
  • localname为本包中的名字
  • importpath.name为引入包的路径及其名字,可省略。

在使用该指令前,需要import unsafe包。

该指令写在localname上,但localname可以是importpath.name的别名,也可以是它的实现,即可以是在本包中定义,也可以不是定义。下面就以具体例子来说明:

一、localname函数在本包未实现,相当于是别名

可以看Go源码中time包的runtimeNano函数,如下图:
在这里插入图片描述
runtimeNano函数在此并未实现,只是提供了一个声明,使用//go:linkname runtimeNano runtime.nanotime来告诉编译器该函数使用runtime包中的nanotime函数实现,这里相当于只是一个别名。该函数的定义如下图所示,但是分为nofakefake两种版本:

在这里插入图片描述

在这里插入图片描述

这种用法比较容易理解,定义好一个函数后,可以在其它包中进行多次go:linkname创建别名。

二、localname函数在本包实现

细心的读者应该发现了上图中time_now函数了,即通过//go:linkname time_now time.now指示time包中的now函数使用本包(runtime包)中的time_now函数,当然time包中还是需要有一个now函数的声明,就在前面nanotime函数的上方:

在这里插入图片描述
可以看到now函数上面的注释没有任何编译器指令。

这种用法比较容易出错,很容易出现missing function body错误,这是因为Go在编译时会添加-complete将该包作为一个纯Go包来编译,即该包中不包括非Go组件。
在这里插入图片描述

遇到这种情况,有两种方式解决:

  • 在该包中添加一个空的.s文件,随便取一个名字,比如empty.s
  • 在函数前添加//go:linkname localname格式的指令,注意没有importpath.name

三、实例

新建一个目录demo,使用VSCode打开,其目录结构如下:

$ tree -a
.
├── .vscode
│   ├── launch.json
│   └── tasks.json
├── case3
│   ├── case3.go
│   ├── empty.s
│   └── internal
│       └── priv.go
├── go.mod
├── main.go
├── outer
│   ├── internal
│   │   └── inter.go
│   └── outer.go
├── private
│   └── private.go
└── public
    └── public.go

8 directories, 11 files

在这里插入图片描述

main.go

package main

import (
	"demo/outer"
	"demo/public"
)

func main() {
	public.Demo()
	outer.Outer()
}

go.mod

module demo

go 1.22.0

public.go

package public

import (
	_ "demo/private"
	_ "unsafe"
)

//go:linkname foo demo/private.foo
func foo()

func Demo() {
	foo()
}

private.go

package private

import (
	"fmt"
)

func foo() {
	fmt.Println("Private foo")
}

outer.go

package outer

import (
	_ "demo/outer/internal"
	_ "unsafe"
)

//go:linkname Outer
func Outer()

inter.go

package internal

import (
	"fmt"
	_ "unsafe"
)

//go:linkname inter demo/outer.Outer
func inter() {
	fmt.Println("internal.inter")
}

case3.go

package case3

import _ "demo/case3/internal"

func Foo()

empty.s是一个空文件,用于告诉编译器,本包不是一个纯Go组件包

priv.go

package internal

import (
	"fmt"
	_ "unsafe"
)

//go:linkname f demo/case3.Foo
func f() {
	fmt.Println("internal.f")
}

tasks.json

{
	"version": "2.0.0",
	"tasks": [
		{
			"type": "go",
			"label": "go: build workspace",
			"command": "build",
			"args": [
				"./..."
			],
			"problemMatcher": [
				"$go"
			],
			"group": {
				"kind": "build",
				"isDefault": true
			},
			"detail": "cd d:\\go; go build ./..."
		}
	]
}

launch.json

{
    // 使用 IntelliSense 了解相关属性。 
    // 悬停以查看现有属性的描述。
    // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Launch Package",
            "type": "go",
            "request": "launch",
            "mode": "auto",
            "program": "${workspaceFolder}",
            "preLaunchTask": "go: build workspace"
        }
    ]
}

如果对你有帮助,欢迎点赞收藏!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/417638.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于JAVA的毕业设计分配选题系统 开源项目

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 专业档案模块2.2 学生选题模块2.3 教师放题模块2.4 选题审核模块 三、系统展示四、核心代码4.1 查询专业4.2 新增专业4.3 选择课题4.4 取消选择课题4.5 审核课题 五、免责说明 一、摘要 1.1 项目介绍 基于JAVAVueSpri…

Go语言必知必会100问题-10 小心类型嵌入导致的问题

小心类型嵌入导致的问题 在定义结构体时,Go语言支持通过类型嵌入的形式定义结构体字段。但是,如果我们没有真正理解类型嵌入的意义,有时可能会导致意想不到的行为。本文将主要分析如何嵌入类型,类型嵌入的作用以及可能出现的问题…

lv20 QT对话框3

1 内置对话框 标准对话框样式 内置对话框基类 QColorDialog, QErrorMessage QFileDialog QFontDialog QInputDialog QMessageBox QProgressDialogQDialog Class帮助文档 示例:各按钮激发对话框实现基类提供的各效果 第一步:实现组件布局&…

Redis 之三:发布订阅(pub/sub)

概念介绍 Redis 发布订阅 (pub/sub) 是一种消息通信模式,它允许客户端之间进行异步的消息传递 Redis 客户端可以订阅任意数量的频道。 模型中的角色 在该模型中,有三种角色: 发布者(Publisher):负责发送信…

【Hudi】核心概念

https://www.bilibili.com/video/BV1ue4y1i7na?p17&vd_sourcefa36a95b3c3fa4f32dd400f8cabddeaf 大数据新风口:Hudi数据湖(尚硅谷&Apache Hudi联合出品) 1 基础概念 1.1 时间轴(TimeLine) 1.2 文件布局(File Layout) 1.3 索引(In…

Unity-PDF分割器(iTextSharp)

PDF分割器 Unity-PDF分割器前言核心思路解决过程一、Unity安装iTextSharp二、运行时计算将要生成文件的大小三、分割核心代码四、使用StandaloneFileBrowser五、其他的一些脚本六、游戏界面主体的构建MainWindowWarningPanel & FinishPanel By-Round Moon Unity-PDF分割器 …

浅谈 Linux 网络编程 socket

文章目录 socket 介绍 socket 介绍 socket 被翻译成 网络套接字,这个名字实在是不好理解,我更愿意称为"插槽"。 忽略 socket 的中文名,先无脑记住两个规则: ① 记住,一个文件描述符(fd) 指向一个 socket&…

同芯.共赢 | 暴雨服务器亮相AMD EPYC合作伙伴峰会

2月29日,AMD EPYC合作伙伴峰会活动在北京成功举行,暴雨作为AMD重要生态合作伙伴应邀参加。作为AMD开年首场活动,此次活动意义非凡,AMD在现场向合作伙伴分享了AMD数据中心全新产品路线、解决方案以及生态建设领域的最新进展。 AMD是…

android开发平台,Java+性能优化+APP开发+NDK+跨平台技术

开头 通常作为一个Android APP开发者,我们并不关心Android的源代码实现,不过随着Android开发者越来越多,企业在筛选Android程序员时越来越看中一个程序员对于Android底层的理解和思考,这里的底层主要就是Android Framewok中各个组…

机器学习专项课程03:Unsupervised Learning, Recommenders, Reinforcement Learning笔记 Week02

Week 02 of Unsupervised Learning, Recommenders, Reinforcement Learning 课程地址: https://www.coursera.org/learn/unsupervised-learning-recommenders-reinforcement-learning 本笔记包含字幕,quiz的答案以及作业的代码,仅供个人学习…

二分查找讲解

关于我为什么要写单独开一篇文章写二分,实际上那么多困难的算法,比如线段树,并查集等等都没有难倒我,我最近却被二分难倒了,而且是两次,两次在赛场上做不出来二分的应用题,于是我决定写一篇二分查找的算法总结.刚接触算法的时候本来是要写一篇的,但后面因为各种原因搁置了,现在…

R语言数学建模(二)—— tidymodels

R语言数学建模(二)—— tidymodels 文章目录 R语言数学建模(二)—— tidymodels前言一、示例数据集二、拆分数据集2.1 拆分数据集的常用方法2.2 验证集2.3 多层次数据2.4 其他需考虑问题 三、parsnip用于拟合模型3.1 创建模型3.2 …

腾讯云优惠券领取的三个渠道,先领券再下单!

腾讯云代金券领取渠道有哪些?腾讯云官网可以领取、官方媒体账号可以领取代金券、完成任务可以领取代金券,大家也可以在腾讯云百科蹲守代金券,因为腾讯云代金券领取渠道比较分散,腾讯云百科txybk.com专注汇总优惠代金券领取页面&am…

禁止safari浏览器网页双击缩放功能

普通浏览器 普通浏览器&#xff0c;只需要增加meta标签禁止缩放功能就行了 <meta content"widthdevice-width, initial-scale1.0, maximum-scale1.0, user-scalable0;" name"viewport" /> user-scalableno或0 //禁止双指缩放页面initial-scale1.0…

企业文件图纸加密有哪些?图纸文件加密防泄密软件如何选?

在现在的市场发展中&#xff0c;对于企业的图纸文件安全问题越来越重视&#xff0c;如设计图纸&#xff0c;重要文件等&#xff0c;一旦泄漏就会给企业造成巨大的经济损失。所以对企业管理者来讲&#xff0c;如何才能选择一款好用的适合本企业的图纸文件加密软件是非常重要的&a…

【C++】手把手教你手搓模拟实现string类

前言 string类一直都是C的经典问题&#xff0c;之前的文章已经对string类做了一个基本的介绍&#xff08;string类的基本常用接口&#xff09;&#xff0c;为了更好理解string类的功能&#xff0c;此篇文章将手把手教你带你手搓模拟实现string类&#xff0c;快来一起学习吧&am…

Spring 事务传播机制

事务传播机制&#xff1a;多个事务⽅法存在调⽤关系时, 事务是如何在这些⽅法间进⾏传播的。 ⽐如&#xff1a;有两个⽅法A&#xff0c;B都被 Transactional 修饰,&#xff0c;A⽅法调⽤B⽅法 A⽅法运⾏时, 会开启⼀个事务。当A调⽤B时&#xff0c; B⽅法本⾝也有事务&#xf…

Pod 进阶

目录 资源限制 健康检查 资源限制 当定义 Pod 时可以选择性地为每个容器设定所需要的资源数量。 最常见的可设定资源是 CPU 和内存大小&#xff0c;以及其他类型的资源。 当为 Pod 中的容器指定了 request 资源时&#xff0c;代表容器运行所需的最小资源量&#xff0c;调度器…

打造去中心化透明储蓄罐:Solidity智能合约的又一实践

一、案例背景 传统的储蓄罐通常是由个人或家庭使用&#xff0c;用于存放硬币或小额纸币。然而&#xff0c;这样的储蓄罐缺乏透明性&#xff0c;用户无法实时了解储蓄情况&#xff0c;也无法确保资金的安全性。 通过Solidity智能合约&#xff0c;我们可以构建一个去中心化…

外汇天眼:外汇市场有哪些功能?

外汇市场有三个方面的功能&#xff0c;一是实现购买力的国际转移&#xff0c;二是提供资金融通&#xff0c;三是提供外汇保值和投机的市场机制。 实现购买力的国际转移 国际贸易和国际资金融通至少涉及到两种货币&#xff0c;而不同的货币对不同的国家形成购买力&#xff0c;…