名字在 golang 中的重要性和在其他任何一种语言是一样的。他们甚至含有语义的作用:在一个包的外部某个名字的可见性是由这个名字首字母是否是大写来决定的。

有时为了更好的组织代码或者在其他包使用某些隐藏的函数时需要克服这种限制。

在过去美好的日子,有 2 种实现方式,它们能绕过编译器的检查:不能引用未导出的名称 pkg.symbol

旧的方式,现在已经不再使用 - 汇编级隐式连接到所需符号,称为 assembly stubs ,详见 go runtime, os/signal: use //go:linkname instead of assembly stubs to get access to runtime functions

  • 现行的方式 - go 编译器通过 go:linkname 支持名称重定向,引用于 11.11.14 dev.cc code review 169360043: cmd/gc: changes for removing runtime C code (issue 169360043 by r…@golang.org) ,在 http://github.com 的 issue 上有可以找到 cmd/compile: “missing function body” error when using the //go:linkname compiler directive #15006

用这些技巧我曾设法绑定 golang 运行时调度器相关的函数用以减少过度使用 go 的协程和内部锁机制导致的 gc 停顿。

使用 assembly stubs

想法很简单 - 为需要的标识符提供直接跳转汇编指令 stubs 。链接器并不知道标识符是否已导出。

详见旧版的代码 src/os/signal/sig.s :

// Assembly to get into package runtime without using exported symbols.
// +build amd64 amd64p32 arm arm64 386 ppc64 ppc64le#include "textflag.h"#ifdef GOARCH_arm
#define JMP B
#endif
#ifdef GOARCH_ppc64
#define JMP BR
#endif
#ifdef GOARCH_ppc64le
#define JMP BR
#endifTEXT ·signal_disable(SB),NOSPLIT,$0
JMP runtime·signal_disable(SB)TEXT ·signal_enable(SB),NOSPLIT,$0
JMP runtime·signal_enable(SB)TEXT ·signal_ignore(SB),NOSPLIT,$0
JMP runtime·signal_ignore(SB)TEXT ·signal_recv(SB),NOSPLIT,$0
JMP runtime·signal_recv(SB)

signal_unix.go 的绑定如下:

// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windowspackage signalimport ("os""syscall"
)// In assembly.
func signal_disable(uint32)
func signal_enable(uint32)
func signal_ignore(uint32)
func signal_recv() uint32

使用 go:linkname

为了使用这种方法,代码中必须 import _ "unsafe" 包。为了解决 go 编译器 -complete 参数的限制,一种可能的方法是在 main 包目录加一个空的汇编 stub 文件以禁用编译器的检查。

详见 os/signal/sig.s:

// The runtime package uses //go:linkname to push a few functions into this
// package but we still need a .s file so the Go tool does not pass -complete
// to the go tool compile so the latter does not complain about Go functions
// with no bodies.

这个指令的格式是 //go:linkname localname linkname。使用这种方法可以将新的标识符链接(导出)或绑定到已存在的标识符(导入)。

用 go:linkname 导出

runtime/proc.go 中一个函数的实现

...//go:linkname sync_runtime_doSpin sync.runtime_doSpin
//go:nosplit
func sync_runtime_doSpin() {procyield(active_spin_cnt)
}

这里明确地向编译器指示,将另一个名字添加到 sync 包的 runtime_doSpin 函数代码中。并且 sync 包简单的重用了在 sync/runtime.go 中的代码:

package syncimport "unsafe"...// runtime_doSpin does active spinning.
func runtime_doSpin()

用 go:linkname 导入

net/parse.go 中有一个很好的例子:

package netimport (..._ "unsafe" // For go:linkname
)...// byteIndex is strings.IndexByte. It returns the index of the
// first instance of c in s, or -1 if c is not present in s.
// strings.IndexByte is implemented in  runtime/asm_$GOARCH.s
//go:linkname byteIndex strings.IndexByte
func byteIndex(s string, c byte) int

使用这种技巧的方法:

import _ "unsafe" 包。 提供一个没有函数体的函数,比如: func byteIndex(s string, c byte) int 在定义函数前,正确的放上//go:linkname 指令,例如 //go:linkname byteIndex strings.IndexByte,byteIndex是本地名称,strings.IndexByte是远程名称。 提供 .s 后缀的 stub 文件,以便编译器绕过 -complete 的检查,允许不完整的函数定义(译注:指没有函数体)。

例子 goparkunlock

package mainimport (_ "unsafe""fmt""runtime/pprof""os""time"
)// Event types in the trace, args are given in square brackets.
const (traceEvGoBlock        = 20 // goroutine blocks [timestamp, stack]
)type mutex struct {// Futex-based impl treats it as uint32 key,// while sema-based impl as M* waitm.// Used to be a union, but unions break precise GC.key uintptr
}//go:linkname lock runtime.lock
func lock(l *mutex)//go:linkname unlock runtime.unlock
func unlock(l *mutex)//go:linkname goparkunlock runtime.goparkunlock
func goparkunlock(lock *mutex, reason string, traceEv byte, traceskip int)func main() {l := &mutex{}go func() {lock(l)goparkunlock(l, "xxx", traceEvGoBlock, 1)}()for {pprof.Lookup("goroutine").WriteTo(os.Stdout, 1)time.Sleep(time.Second * 1)}
}

源码

可在这里获取 https://github.com/sitano/gsysint

相关文章

  • Docker Windows install instructions on the state of 4 August 2016 04 Aug 2016
  • PowerShell ducklish typed 25 Apr 2016
  • Approach into strong typed configuration management DSL with FAKE, F#, WinRM and PowerShell 15 Mar 2016

原文章链接:https://studygolang.com/articles/12134

onclick如何调用含参函数_在 golang 中如何调用私有函数(绑定隐藏的标识符)相关推荐

  1. python什么是高阶函数_说说 Python 中的高阶函数

    高阶函数(higher-order function)指的是:接受一个函数为参数,或者把函数作为结果值返回的函数1. 1 sorted() 比较常见的高阶函数是 sorted(),其内部的关键字参数 ...

  2. python enumerate函数_关于python中enumerate和zip函数的用法及举例

    关于python中enumerate和zip函数的用法及举例 关于enumerate函数: enumerate函数可以同时返回列表或元组等可迭代对象的下标和内容,但实际上,enumerate函数实际返 ...

  3. 怎样使用python画复杂函数_在python中绘制复杂的函数?

    我试图在python中绘制一个带有可变参数的复杂函数,并且发现我无法解释的差异.我的代码如下所示:import matplotlib.pyplot as plt from numpy import p ...

  4. mysql中没有内置函数_[mysql]MySQL中的内置函数

    用在select  语句,以及子句where   order  by    hacing  中    update   delete 函数中可以将字段名作为字段来用,变量的值就是这个列对应的每一行记录 ...

  5. python无返回值函数_理解Python 中无返回值函数的问题

    例如 list 的 append 操作就是无返回值的,换句话说就是不能进行形如 list = [] list.append(1).append(2) 这样的连续操作 注意函数返回的数据类型注意是 li ...

  6. mysql有什么好用的小函数_盘点MySQL中比较实用的函数

    之前小编在工作中遇到一些处理数据的问题,例如完成日期格式化,获取几天后的时间,生成指定格式的编码等问题,这时候小编经常会写一大堆逻辑代码来进行处理,还自己感觉自己很流弊的样子,后来却发现同事遇到相同的 ...

  7. golang 没有名字参数_在 Golang 中用名字调用函数

    上个星期,我写了篇<Function call by name in Golang>.由于是英文的,所以被人诟病(说谁,谁知道!).好吧,现在用中文重新写一遍. Golang 中的函数跟 ...

  8. python 实例方法调用时可以忽略第一个参数_盘点Python中易忽略的函数

    Python 内置函数 1.ord() 函数是 chr() 函数(对于8位的ASCII字符串)或 unichr() 函数(对于Unicode对象)的配对函数,它以一个字符(长度为1的字符串)作为参数, ...

  9. 未捕获typeerror: $形象。cropper不是函数_没有学不会的python--细说自定义函数的细节...

    没有学不会的python 函数是什么? 老调常谈,还是那老一套,学习一个东西前,先搞懂是什么,再来学习怎么用. 函数函数,如果你是刚经历过高考肯定很熟悉,数学中就经常出现这个名词,比如什么sin函数, ...

最新文章

  1. 哈佛CASTER | 基于化学子结构表征预测药物相互作用
  2. R语言实战应用精讲50篇(一)-万字长文干货R语言ggplot2包图形绘制
  3. mysql函数包含的意思_MYSQL函数
  4. matlab连续信号离散化_MATLAB开发自动驾驶第八课-控制信号帧的回放以进行标签化处理...
  5. 用matlab仿真pwm整流器的方法,MATLAB-PWM整流仿真模块建立详解.pdf
  6. 原生JS实现移动端模块的左右滑动切换效果,基于vue、stylus
  7. j.u.c系列(11)---之并发工具类:Exchanger
  8. android分开两个线程做事,android开发教程之handle实现多线程和异步处理
  9. u8虚拟服务器端口,用友u8服务器参数配置
  10. [SDOI2009] HH去散步 (矩阵乘法)
  11. IE无法浏览网页,而QQ可以上解决方案
  12. php laravel 面试,当面试关问你Laravel Facade,说出这几个关键词就可以
  13. 数据科学和人工智能技术笔记 十九、数据整理(下)
  14. opencv修改像素值
  15. 共享该文件当前不能用户此计算机,局域网共享常见问题解决汇集
  16. 电脑技巧:电脑内存不足怎么办?看完你就会了!
  17. element中form表单输入非负数验证
  18. Contect、SharedPreferences及Intent学习小记
  19. 支付通道对接流程有哪些?
  20. ECCV2020 Flow-edge Guided Video Completion20论文翻译

热门文章

  1. LiveVideoStack主编观察02 / 附赠专属优惠码
  2. 泛广电领域的卫星传输和公网传输
  3. AV1:下一代视频标准—约束定向增强滤波器
  4. mac下RTSP服务器搭建(ZLMediaKit)
  5. 《Go语言圣经》学习笔记 第三章 基础数据类型
  6. 【H264/AVC 句法和语义详解】(五):Exp-Golomb指数哥伦布编码(理论篇)
  7. 基于 Flink 的超大规模在线实时反欺诈系统的建设与实践
  8. 浅析HDFS的副本存放策略
  9. Scala _04Scala字符串
  10. leetcode 721. Accounts Merge | 721. 账户合并(HashMap版并查集)