本文是对涛叔在Go夜读119期119 Go monkey patch 的原理及应用的学习与记录
关于猴子补丁
Python异步库gevent有一个猴子补丁模块,from gevent import monkey; monkey.patch_all(),可以将python标准库里面大部分的阻塞式系统调用,包括socket、ssl、threading和select等,变为协作式运行
猴子补丁的这个叫法起源于Zope框架(1998年就诞生的一个Python Web框架),大家在修正Zope的Bug的时候经常在程序后面追加更新部分,这些被称作是“杂牌军补丁(guerilla patch)”,后来guerilla就渐渐的写成了gorllia(猩猩),再后来就写了monkey(猴子),所以猴子补丁的叫法是这么莫名其妙的得来的。
后来在动态语言中,不改变源代码而对功能进行追加和变更,统称为“猴子补丁”。所以猴子补丁并不是Python中专有的。猴子补丁这种东西充分利用了动态语言的灵活性,可以对现有的语言Api进行追加,替换,修改Bug,甚至性能优化等等。
使用猴子补丁的方式,gevent能够修改标准库里面大部分的阻塞式系统调用,包括socket、ssl、threading和 select等模块,而变为协作式运行。也就是通过猴子补丁的monkey.patch_xxx()来将python标准库中模块或函数改成gevent中的响应的具有协程的协作式对象。这样在不改变原有代码的情况下,将应用的阻塞式方法,变成协程式的。
python协程初步–gevent库使用以及解释什么是猴子补丁monkey_patch
Go实现猴子补丁
1 | package main |
最好的方式是找到main()调foo()的地方,将其指向bar().
但Go中实现不了这种效果,只能找到foo()指向的内存区域,将该区域前面的指令替换为跳转到bar()
不同CPU的跳转指令不同,下面以amd64架构为例
只要内存布局一样,不同类型的指针是可以通过unsafe.Pointor强转的,如float64类型的指针可以转为int64类型的指针
unsafe包的用处就是绕过编译器对指针类型转换的检测逻辑,但程序员需自己保证两种指针的底层数据结构一致(即不让编译器做类型检查)
//todo
一些相关的库
最早有个bouk/monkey项目,作者是荷兰人,但已经不维护了
Go语言实现猴子补丁
Go语言实现猴子补丁【二】
Go语言实现猴子补丁【三】
原文链接: https://dashen.tech/2010/03/26/Go实现猴子补丁/
版权声明: 转载请注明出处.