熟悉 Go 语言的开发者一般都非常了解 Goroutine 和 Channel 的原理,包括如何设计基于 CSP 模型的应用程序,但是 Go 语言的插件系统是很少有人了解的模块,通过插件系统,我们可以在运行时加载动态库实现一些比较有趣的功能。
8.1.1 设计原理
Go 语言的插件系统基于 C 语言动态库实现的,所以它也继承了 C 语言动态库的优点和缺点,我们在本节中会对比 Linux 中的静态库和动态库,分析它们各自的特点和优势。
1.静态库或者静态链接库是由编译期决定的程序、外部函数和变量构成的,编译器或者链接器会将程序和变量等内容拷贝到目标的应用并生成一个独立的可执行对象文件1;
2.动态库或者共享对象可以在多个可执行文件之间共享,程序使用的模块会在运行时从共享对象中加载,而不是在编译程序时打包成独立的可执行文件2;
由于特性不同,静态库和动态库的优缺点也比较明显;只依赖静态库并且通过静态链接生成的二进制文件因为包含了全部的依赖,所以能够独立执行,但是编译的结果也比较大;而动态库可以在多个可执行文件之间共享,可以减少内存的占用,其链接的过程往往也都是在装载或者运行期间触发的,所以可以包含一些可以热插拔的模块并降低内存的占用。
![](data:image/png;base64,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)
图 8-1 静态库与动态库
使用静态链接编译二进制文件在部署上有非常明显的优势,最终的编译产物也可以直接运行在大多数的机器上,静态链接带来的部署优势远比更低的内存占用显得重要,所以很多编程语言包括 Go 都将静态链接作为默认的链接方式。
插件系统
在今天,动态链接带来的低内存占用优势虽然已经没有太多作用,但是动态链接的机制却可以为我们提供更多的灵活性,主程序可以在编译后动态加载共享库实现热插拔的插件系统。
![](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAscAAAEACAYAAABf89u/AAAgAElEQVR4nO3daZRc1X33++85p+auqp7nSQOaByQkxIwAY0aDARtsiOfYjoc4dp6sPLkr9671PC/uWs+L3Nzkxutx4sSxY4PBGGNj5hmMQAKhWUKz1OpWa+p5rPmcc190qaSmW2joblWr+/dhseg+tWvXv0qH0q927bO30d3b7yIiIiIiIpj5LkBEREREZLJQOBYRERERyVI4FhERERHJUjgWEREREclSOBYRERERyVI4FhERERHJUjgWEREREclSOBYRERERyfLkuwAREYB4PE5sMJ773TANQqEggUBg1Pb9/QOkkil8fi+RSOSM/TqOQ093LxhQUlI87LbBgUESiSShghDB4MjHSafTdLR30tfXT2VVBUVFhSPadHV14zpn3kspEgnj8/sA6OvtI53OEAgGKCgI5drYtkNPdw+Wx6KwMIphGGfs72wy6QzHT7Qx0D9ASUkxJaUleDxW7vaBgUGSiSQer4fCwuiI+w8OxkjEE3h9XqLR4a9rMpmivb2dgf5BSkqKKCsvwzRPjbF8/M/wTE4+f9d16e3tw87Yo7YzDIPCoiiWZeG6Ll2d3QCUlBYPe41Onguj1Swicr4UjkVkUnh/3Ye89sqbI45HIhHuvvcOFi6cPyzkPffHF9mxfScLF87nS1/94hn77e3t41/++V/xeCz+r//xd8Nue/WVN/lw/UZuu/NWbrrp+tzxTMZm9649/O63z5BKpXLHa+tq+bMvPUhRcVHu2E9+/O/EYmcOhI986UEWL1kEwBO/form5sPMmNnIt7/z9Vybnu4e/vEf/oXqmiq++/1v4vFc2Fvzvr0HeOLxp0jEE7lj4XABDz70ALMum4FlWbSdaOfnP/slhYWF/NVffw9/NrgDOLbDT3/yMzo6urjplhu47fZPAeC6LgcONPH73/1x6INGlsfj4ZEvPcScubOxLIv1H2zglZfeOGud1153FZ+5905s2+bRXz7BsaPHR23n8/n4/l99m/LyMmzb5h//4V8A+NKXv8DCxQty7X7xn49y/NgJ5s+fy1e+/sj5vWgiIh+jaRUiMqkUFkWZv3Aec+ZdRklpMf39/fzm10/x8suvX7Qann3mBZ749VOkUilKS0tYsnQR0WiEI61H+OD9DcPaVlZWUF1dSXV1Ze5YcXFR7lggGBzRf0vzYQ7sOziuNe/ZvY/HHv0NiXiCoqJClixdRHl5KYODMX792G9ob+8AYMbMBmpqaujp6WXrlm3D+ti//yAdHV0UFIS4cfWpDwvNzYd59L+eoKe7l2g0wuLFCygrLyWTyfD4Y09y/PgJAArC4dzzrq6uJBwuAMDv9w87Hh1lxLqkpGhYm+rqSqqqKkb9oPDOn97L/dze3sGJ421jfwFFRLI0ciwik8rsy2bx+QfvA4ZGLD/asYvfPvl7dmzdwZ133oplWWfpYWx27dzDhg83AXDvfXdz9TVXApBOZ1j//odcsXLZsPbfOm0E+O//7n8CcMfdn2ZJdrR4NKZp8sILr/Ld738Tr3fsb8Ou67Ju7QekU2mWXr6Yh774QG66w8EDTbQ0t1JZUZF77GuuvZKnfvsMr7z0OouXLCIUGgrwGzdsxjAMbr51NYGAP9f/+vc3kE6nuXLVCu7/3D25401NzXR2dFFbWwPAypXLWblyee72V156nT+9/S6NMxr46tcf+cTpIvd89i7mzZ971ucaiUZoaWmlt6eXwqJCPvxgI8Fg4BNH70VEzodGjkVk0jIMg3nz51BUWEh//wDpdHpCHy+TyfDG628DMHfeZblgDOD1erjuhmsIjjISfL4aZ9TT3tbOiRMnxtwXDM2rjmenUnx8Pu6s2TO56ZYbMMxTx5avWEZ1dRXxeIJdO3cDQ1M7dmzfic/nY/HihcP67+zqAhg2Txpg5sxGVl65nIupuKgIyzJpbm4lk86we/deysrLLmoNIjK1KRyLyKTmOC7JVAqv14tlTeyXXZmMzeBgDID7P3fvhD3OZXNmYds2b7+5Zlz6syyLGY31ALzz9rs8/dQzHGk9+on3ufW2mzFNkw0fbsZ1XZ577mVc12X1TdePuKjt5Cj42vc+4Kkn/8DRI8fGpe7TZTIZ0un0sH9dd+SFjj6/D4/HS9PBQ/QPDDDQP0DVaVNaRETGStMqRGRSyaTT9PcP4LoOscE4769dT39fPzW11VjWxH6et22beCxOIODPBcR0Ok3zocM4zqkVFWbOmoHX673gxykvL6dxRgM7P9rN4ZZWIpHwmGu/9fZbOH6inX1797Np41Y2b97O3Lmzufa6q5k5q3HE3N1Zs2dQWBSl+VALWzZto7mpmZLSElbffP2IvlesXMbePfs5eKCJzZu2snnTVubOm8ONq6+jvqF2TK/FSb9+9Lcjjn33+9+kvqFu2DHLMmloqOXggSbmzbuMZDJFY2M96z82F1xE5EIpHIvIpPLRjt3s2b0fcLFth0wmg2EYfPa+zwxbNmwiuK6Dbdt4vafm2w70D/L4Y78lkTi1AsTf/O1fUVpWcsGPk0qluP9z9/Djf/433l2zjs9l51iPhdfr5Stfe5iWQ4f53e/+SHdXN3t272Pf3gPUN9TxtW98adjKFH6/nwc+91n+8z9+ye+ffhbbtrnuhmtGnRccDAb56tcf4cD+Jn7/9LP09faxd88+9u87wJw5s/ny1x4e85+NYRgjHnu0Kcq2bfPp227hX3/yM15//W3qG+ooLi4e2VBE5AIpHIvIpBIMBSkrK8U0DCLRCOXlZSxbvoSS0gsPo2e+EGzoa3srG+wsy5O7uMtxHCzLIhgKcvudnyKTsXnhuZeH3e9C2Y5DSUkxNTVVHNjfBK47LhcaWpbFzNkz+Ou/+T4HDjSxeeNWdmzfSUvzYd5ft57VNw0fFZ592UxmzGzkUFMzoYIQq65a+Yl9z513GX/7dz9k//6DbNqwhe3bPmLPnn289MKr3H3PHWOq/Stfe/icLshzXairr6WstJRjR4/z8J89OGxUX0RkrBSORWRSmTvvstxqFePB4/Hg9XqIxxO4rjssKCcSSeDU5iAej0UoFGJgYJCNGzaz6qqVBAJ+rrr6SlzXPS0cj5Hr4vF4uO6Ga/nN40/x1ltrho3qjpXH42HevDnMmzeHPz7zPB+s28CO7TtHhGOAuroaDjU1M3PWjBEX3I3Gsqxc34ZhsG3rDpqbD2Pb9oSvJAIMpWNgztzZ2LttGhrq6OjonPjHFZFpQxfkiciU5vV68Pl82LbNti3bh912/NgJDMOgrLwUyIbK7Ojli8+/Qnd3z4TWtnjJAurqa3lvzTrS6cyY+tq+7SM2btwy4ngkMrSm8FhW2WhqOsS2rTtGHK+pqQaGAvNYdvW7EJ++/Rb+4jvfIKId8URknGnkWEQuaZ2dXaz509oRx+fOv4zKygoCgQBLli7kT2+/xzN/eIGe3j7C4QK2b/uI9vYOyspLc9soG4bBLbfeyO7de2hv6+AX//kYV6y4nKKiQo4fG33ZtXVr15P5WLDdvXMvPV1DO8ktWDgvF74/bmjN4VU89eQfxvISEIvFefH5V+jvH2Dnjl00NNRRWFRIT3cv76/9ANM0uWLF5RfUd09PD4/98kni8TgbN2xm1qwZRIsK6e7q5q033sEwDJYsXTTmOcc7tu+i7UTHiOOXL18y6pbQgUDgjFuLi4iMhcKxiFzSTpxo46UXXx1xvCASorJyaOOL2+64lcMtR2hqauaVl07ttBcIBLj3vs8MC1l+v58//9ZX+fd//TldnV28+vLQdsiGMTSyfP2N1w6b//zGa2+N2IBi86atuZ+LSwrPGI4B5i+Yh2maOI5zns/8lFAoyN333MHvf/csu3ftZdfOPbnbLMtiyeWLWHr54gvqu6ioiAe/+ABP/eb37N93kH17Dwzr+5rrVnHtdVddcO0nbdywedTjjTPqRw3HIiITxeju7R/blSUiIuOgo6OT9rZ2CosKc1/Xf5LW1iP09/Wf8faammoKiwpzv6fTaQ4daqG9rYN4LE5FZQX19TUUFReNev9MJsPhllY6Ojrp6+2nqqaS0tISKisrhk0h2LtnH7Z95gvCautqc+HuUFML8XiM6ppqik6rraWllcGBAfyBADNnNl7wFIX+/gHa29rpaO+kt6+P8vJyKqvKqa6uOuN9Tpxoo6uzi0g0Ql1d7Rnb9fb20dnRSUdHF/19/ZSWlVBRWUFVVcUZR43b2trp7OikIBym4WNLssHQzn5NTc0kT1sJZDiDGTMaCIaCuK7L7l17CRWEaMyu6XzS4GCMluYWwuHwiKXfRETOl8KxiIiIiEiWLsgTEREREclSOBYRERERyVI4FhERERHJUjgWEREREclSOBYRERERydI6xyIiEyiRTGIYBh7LujjbK4uIyJgoHIuITJBMJsObaz+guqKM7t5+Vl+1UgFZRGSSUzgWEZlAAb+fZQsXsGHbDpqPHMXr8dDW2UUmk6GirIzaqgq2795LOp2hIBRk4ZzZbP5oFyuXLuZAcwuWaVJdUcGWnbvJ2BnKS0qYM7OR19aspaykmP6BGNetXEZnTy/7DzVjGAazGuopLynmw207sEyTgN/PormX0XzkKJ3dPQAsmTcHv9+f51dHRGTy0ZxjEZGLIBgMkkylyDg2juOwatlSZtbX4vN6mVFfh9fr4cjxEziui+04DMbjHGg+THVFBfsONeM6LpFwAdv37COTyZDJ2CyeN4fykmKOtnWwc+9+/D4/0XCYlqPHcF2Xzq6hIDyjrhbTNBmMxRkYjFFXXaVgLCJyBgrHIiITyHVcunp6OdHeQXVFOQDhUCi3RXRHVzfbd+1lVkM9Xo8HXKirrmLrR7upLC/H7/cRLijA8pjUVVVyzYplQ1MzDDAwME0D13Hw+Xz4/T7qqiuZN2sGANetXM6M+lrWbdrCYCxObVUlyxbN52BLKwdbDuftNRERmcwUjkVEJohhGJiWya79B1kwZzZF0SgBn59gMJBrUxAKAi57DzZRUVaGYRhUl5eRtm1m1tcA0FhbjcfjYevOPfQPDmIYBiWFhRiGQTAYIOD3s2LJQgYGB9myYxeJRBLHcdjX3MKO3fsoLy0hEPDT3tnF5h27wHWprqjI06siIjK5Gd29/W6+ixARmc5cF7IDyWdp5+ZGnM+1zdl+FxGR4TRyLCKSZ+eaVc8l1H68zdl+FxGR4RSORURERESyFI5FRERERLIUjkVEREREshSORURERESyFI5FRERERLIUjkVEREREshSORURERESyFI5FRERERLIUjkVEREREshSORURERESyPPkuQGQqcl132H9FRnP6Vs7jta3z6eeczj/5JCfPOW0pLjKcwrHIOHIcB8dxyNg2adse+t11FVJkGMMYCiSmYWKZJj6PB9M0MU3zgoOK67q58y+VyWA7Do7r4LouOv3kdEPnnoFpmngtC49l5c4/EVE4FhkXJ4NJOp2mKT7A5tQgnU6GJA5OvouTScuDQdgwqfX4uMofpTAQxMoGlfPhOA62bdObiPNBso8jmRQDrkMGpWIZnQn4MSk1PSz3FTAzGMbr9Y7pA5rIVGF09/br3VNkDE4G42QyyaaBbtbasXyXJJegMixuCxRRURDGkx1JPheO45DJZGgbHODVRA8d2BNcqUxF11ohrggX4/f7FZBl2tN3KCJj5LouqVSKfX3dvK9gLBeoA5tXE90MxGLYtn1OU3Fc18W2bQZiMV5NdCsYywV7346xr6+bVCqlaWAy7Skci4zByXDSH4+xzolrCoWMSScOBwf7SKWS5xyOU6kkBwf76NTZJ2PgAOucOP3xc/9wJjJVKRyLjIHruqTTaTriMQY1v1PGyAW223Hi8QS2ffZRYNu2iccTbLfjOvtkzAZx6YjHSKfTCscyrSkci4zBUDhOMZCI42iKnoyDbsskkYifdfTu5LcWiUScbktv5TJ2jgEDiTjptKZWyPSmd1SRMbJth2Q6rZE7GRcZE9LpzDlPq0inM2T0Ti7jwAWS6TS2rSk6Mr3pLVVkDHJry57DV+Ai58rOrpF9NieXcBMZL0723NPIsUxnCsciY6RNFmS8uee4ccy5thM5V66rnRVFFI5FRERERLIUjkVEREREshSORURERESyFI5FRERERLIUjkVEREREshSORURERESyFI5FRERERLIUjkVEREREshSORURERESyFI5FRERERLIUjkVEREREshSORURERESyFI5FRERERLIUjkVEREREshSORURERESyFI5FRERERLIUjkVEREREshSORURERESyFI5FRERERLIUjkVEREREshSORURERESyFI5FZNKLWh68hpHvMmQaMg2DsOXJdxkichHp/3gRwWeYnIyeLmDjYrtu7vYyj4+bImW53x1cXu9rp8/OTHhthZaXb5Y3cjyd5PHOw7hnv4tcQjyGgcWpDz4nz73T/5yvDpdQ5w3kft+XHGBrrG/CazMx+GZZI0UeL092HaE5GZvwxxSR/FM4FhEeKqklZFkAuC5kcNkbH2DdYBdONiS72fxS4fETMi18RudFqc0ywDCG/itTz9XhEhYGI7nfbdelz86wpr+D4+lk9qiLa0DAsKj1BeiyUxelNsMg942FvrkQmT4UjkWEqOXBZ5rsiPdhYFBsebkmUkLU8vBKbxsdmRRPdx0F4K6iShYEImfpcfx0ZdL8or2FQSejUeMpKGhaFFletsf6SLkOQdNilr+AB4preKyzlT47zfsD3UA3tb4gf1Zad9Fqs12Xn7Y3E7UsujLpi/a4IpJfCsciAkDScXirtwM7G0G/WFJHoz+E1zBIumePpSYGDf4gjuvSkornjl8WKMBx4WBycHhbX5A6f5B+O8Ogc2p6xsFEDI8x1Nfpgo5F62n9AswOFNCRTjLo2NT7QjT4AuxODNCWTipIX2Le7e+g37EBaPQF+UJpHYuDEdYOdJ3T/UOWhxqvn/Z0il57KMgGTIs6X4DOdIru7DGDoWlEi0NRAqaVPVeGzpbj6QQDts0sfwHmxwaK445DPFsfQLXPjxeTw6k4UcvLvECYpGuzKz5AynXG+GqISD4pHIvIqFKug2UYGAacS9L0GAZ3FFaSdG1+0d6SO35/cQ0Jx+bHJw4C4DVMPldcTZ0/xNFUnHKvD79hkXEdXOAnbU2ETQ/3FVdjnjYXtTUV54nO1mGl3FdUzaFUjBLL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eh3XhQce/CyFRYXMnTeHuz5zO6lUmr17959XXyIik5FGjkVkSisIhyguKeJQU8uw447jcOzocaprKikoCOWODwzEuPe+u4hEI9gZm40btvDR9l3D7ptMprj+hmu474HP4DguTQebh40+n7Rpw1YuX7aE+QvnMn/hXGKDMf6///cn9PcPnFPtmUyGZ37/HHffcwerb76emz91IzA057kgPLRUW0tLKwf2H2TRkgUsuXwR8XiczZu2UVtbPaK/jvYO/vTWu1x97Sp++N++B0BsMMb/+r//cdgUiE+ya9ce3luzjitXXcHf/f1f5+r5zeO/o7en75z6EBGZzIzu3v5P3kNURGSCJBIJOjo6eO6ZlzjcciSvtdTV1/K9H3yLdWvX88KzL1NfX8ux4yeGrd8bCAb4wY++Q19vHz/9yc+prKxgYHCQwbMsTVZUXEQ0GqHtRDuJROIT256J1+uhsrKCzs6uEWscw9DUhkAgwPHjJ87al2WZVFVVYts27e2d5xyMT2eaBtU11fT19p1z2L8Y6htquee+OykrKyMQmNgdB0VkatLIsYjIaSzLwnEcmpsPn7GNYQzNSDs5beJserp76OnuGVNd6XSG1k/Yra6npxc4tzm/tu0MbXYyBo7javc8EZmSNOdYRIShVSdSqTR25hNGUd2hi9JOX6lBRESmFo0ci4gwtDLEP/yvfyL9CcE3mUzy05/8/IzLqomIyKVP4VhEhKEL9AYHY5/YxnVd4rHxW8dYREQmH02rEBERERHJUjgWEREREclSOBYRERERyVI4FhERERHJUjgWEREREclSOBYRERERyVI4FhERERHJUjgWEREREclSOBYRERERyVI4FhERERHJUjgWkbwzjHxXIFOFziURGSuFYxHJG8MwMAwDv9+X71JkivD7fbnzSkTkQigci0jeGIaBZVmUlpfmuxSZIkrLS7EsS+FYRC6YwrGI5I1hGHg9HmrrqohEw/kuRy5xkWiY2roqvB6PwrGIXDCFYxHJG9M08fl8RCJRFi6ei2kq0MiFMU2DhYvnEolE8fl8mKb+ehORC+PJdwEiMn2ZponP76cwGqW+oZZYLMaBvYeIxRL5Lk0uIaFQgNlzZ1DfUEthNIrP71c4FpELpnAsInljGAYej4dwJEJ5eQWO4xAtDHPk8DG6u3pJpzO4rpvvMmUSMgwDr9dDcUkhtfXVVFZWUl5eQTgSwaNpFSIyBgrHIpJXpmni9/spLi7GsixCwRDFxcXEBmOk0ikcx8l3iTIJmaaJz+sjVBCiqLCIouJiotEofo0ai8gYGd29/RqWEZG8cl0X27ZJp9MkEgkS8TiJZBI7k8HRyLGMwjQMLI+HgN9PIBgkEAjg9Xq1UoWIjJlGjkUk705OrzBNE6/XSygUwnGc3KixplbI6U6GX9M0MU0Ty7JyP4uIjJXCsYhMGqeHHZFzpZFiERlPCsciMuko7IiISL7oOygRERERkSyFYxERERGRLIVjEREREZEshWMRERERkSyFYxERERGRLIVjEREREZEshWMRERERkSyFYxERERGRLIVjEREREZEshWMRERERkSyFYxERERGRLIVjEREREZEshWMRERERkSyFYxERERGRLIVjEREREZEshWMRERERkSyFYxERERGRLIVjEREREZEsw3VdN99FiIiIiIhMBho5FhERERHJUjgWEREREclSOBYRERERyfr/AWORAy6204NQAAAAAElFTkSuQmCC)
图 8-2 插件系统
通过在主程序和共享库直接定义一系列的约定或者接口,我们可以通过以下的代码动态加载其他人编译的 Go 语言共享对象,这样做的好处是主程序和共享库的开发者不需要共享代码,只要双方的约定不变,修改共享库后也不需要重新编译主程序。
type Driver interface {
Name() string
}
func main() {
p, err := plugin.Open("driver.so")
if err != nil {
panic(err)
}
newDriverSymbol, err := p.Lookup("NewDriver")
if err != nil {
panic(err)
}
newDriverFunc := newDriverSymbol.(func() Driver)
newDriver := newDriverFunc()
fmt.Println(newDriver.Name())
}
上述代码定义了 Driver 接口并认为共享库中一定包含 func NewDriver() Driver 函数,当我们通过 plugin.Open 读取包含 Go 语言插件的共享库后,获取文件中的 NewDriver 符号并转换成正确的函数类型,可以通过该函数初始化新的 Driver 并获取它的名字了。
操作系统
不同的操作系统会实现不同的动态链接机制和共享库格式,Linux 中的共享对象会使用 ELF 格式3并提供了一组操作动态链接器的接口,在本节的实现中我们会看到以下的几个接口4:
void * dlopen(const char * filename, int flag);
char * dlerror(void);
void * dlsym(void * handle,
const char * symbol);
int dlclose(void * handle);
dlopen 会根据传入的文件名加载对应的动态库并返回一个句柄(Handle);我们可以直接使用 dlsym 函数在该句柄中搜索特定的符号,也就是函数或者变量,它会返回该符号被加载到内存中的地址。因为待查找的符号可能不存在于目标动态库中,所以在每次查找后我们都应该调用 dlerror 查看当前查找的结果。
8.1.2 动态库
Go 语言插件系统的全部实现都包含在 plugin 中,这个包实现了符号系统的加载和决议。插件是一个带有公开函数和变量的包,我们需要使用下面的命令编译插件:
go build -buildmode=plugin ...
该命令会生成一个共享对象 .so 文件,当该文件被加载到 Go 语言程序时会使用下面的结构体 plugin.Plugin 表示,该结构体中包含文件的路径以及包含的符号等信息:
type Plugin struct {
pluginpath string
syms map[string] interface {}
...
}
与插件系统相关的两个核心方法分别是用于加载共享文件的 plugin.Open 和在插件中查找符号的 plugin.Plugin.Lookup,本节将详细介绍它们的实现原理。
CGO
在具体分析 plugin 包中几个公有方法之前,我们需要先了解一下包中使用的两个 C 语言函数 plugin.pluginOpen 和 plugin.pluginLookup;plugin.pluginOpen 只是简单包装了一下标准库中的 dlopen 和 dlerror 函数并在加载成功后返回指向动态库的句柄:
static uintptr_t pluginOpen(const char * path, char * * err) {
void * h = dlopen(path, RTLD_NOW | RTLD_GLOBAL);
if (h == NULL) { * err = (char * ) dlerror();
}
return (uintptr_t) h;
}
plugin.pluginLookup 使用了标准库中的 dlsym 和 dlerror 获取动态库句柄中的特定符号:
static void * pluginLookup(uintptr_t h,
const char * name, char * * err) {
void * r = dlsym((void * ) h, name);
if (r == NULL) { * err = (char * ) dlerror();
}
return r;
}
这两个函数的实现原理都比较简单,它们的作用也只是简单封装标准库中的 C 语言函数,让它们的签名看起来更像是 Go 语言中的函数签名,方便在 Go 语言中调用。
加载过程
用于加载共享对象的函数 plugin.Open 会将共享对象文件的路径作为参数并返回 plugin.Plugin 结构:
func Open(path string)( * Plugin, error) {
return open(path)
}
上述函数会调用私有的函数 plugin.open 加载插件,它是插件加载过程的核心函数,我们可以将该函数拆分成以下几个步骤:
1.准备 C 语言函数 plugin.pluginOpen 的参数;
2.通过 cgo 调用 plugin.pluginOpen 并初始化加载的模块;
3.查找加载模块中的 init 函数并调用该函数;
4.通过插件的文件名和符号列表构建 plugin.Plugin 结构;
首先是使用 cgo 提供的一些结构准备调用 plugin.pluginOpen 所需要的参数,下面的代码会将文件名转换成 *C.char 类型的变量,该类型的变量可以作为参数传入 C 函数:
func open(name string)( * Plugin, error) {
cPath: = make([] byte, C.PATH_MAX + 1)
cRelName: = make([] byte, len(name) + 1)
copy(cRelName, name)
if C.realpath(
( * C.char)(unsafe.Pointer( & cRelName[0])), ( * C.char)(unsafe.Pointer( & cPath[0]))) == nil {
return nil, errors.New(`plugin.Open("` + name + `"): realpath failed`)
}
filepath: = C.GoString(( * C.char)(unsafe.Pointer( & cPath[0])))
...
var cErr * C.char
h: = C.pluginOpen(( * C.char)(unsafe.Pointer( & cPath[0])), & cErr)
if h == 0 {
return nil, errors.New(`plugin.Open("` + name + `"): ` + C.GoString(cErr))
}
...
}
当我们拿到了指向动态库的句柄之后会调用 plugin.lastmoduleinit,链接器会将它会链接到运行时的 runtime.plugin_lastmoduleinit 函数上,它会解析文件中的符号并返回共享文件的目录和其中包含的全部符号:
func open(name string)( * Plugin, error) {
...
pluginpath, syms, errstr: = lastmoduleinit()
if errstr != "" {
plugins[filepath] = & Plugin {
pluginpath: pluginpath,
err: errstr,
}
pluginsMu.Unlock()
return nil, errors.New(`plugin.Open("` + name + `"): ` + errstr)
}
...
}
在该函数的最后,我们会构建一个新的 plugin.Plugin 结构体并遍历 plugin.lastmoduleinit 返回的全部符号,为每一个符号调用 plugin.pluginLookup:
func open(name string) (*Plugin, error) {
...
p := &Plugin{
pluginpath: pluginpath,
}
plugins[filepath] = p
...
updatedSyms := map[string]interface{}{}
for symName, sym := range syms {
isFunc := symName[0] == '.'
if isFunc {
delete(syms, symName)
symName = symName[1:]
}
fullName := pluginpath + "." + symName
cname := make([]byte, len(fullName)+1)
copy(cname, fullName)
p := C.pluginLookup(h, (*C.char)(unsafe.Pointer(&cname[0])), &cErr)
valp := (*[2]unsafe.Pointer)(unsafe.Pointer(&sym))
if isFunc {
(*valp)[1] = unsafe.Pointer(&p)
} else {
(*valp)[1] = p
}
updatedSyms[symName] = sym
}
p.syms = updatedSyms
return p, nil
}
上述函数在最后会返回一个包含符号名到函数或者变量映射的 plugin.Plugin 结构体,调用方可以将该结构体作为句柄查找其中的符号,需要注意的是,我们在这段代码中省略了查找 init 并初始化插件的过程。
符号查找
plugin.Plugin.Lookup 可以在 plugin.Open 返回的结构体中查找符号 plugin.Symbol,该符号是 interface{} 类型的一个别名,我们可以将它转换成变量或者函数真实的类型:
func(p * Plugin) Lookup(symName string)(Symbol, error) {
return lookup(p, symName)
}
func lookup(p * Plugin, symName string)(Symbol, error) {
if s: = p.syms[symName];
s != nil {
return s, nil
}
return nil, errors.New("plugin: symbol " + symName + " not found in plugin " + p.pluginpath)
}
上述方法调用的私有函数 plugin.lookup 实现比较简单,它直接利用了结构体中的符号表,如果没有找到对应的符号会直接返回错误。
8.1.3 小结
Go 语言的插件系统利用了操作系统的动态库实现模块化的设计,它提供功能虽然比较有趣,但是在实际使用中会遇到比较多的限制,目前的插件系统也仅支持 Linux、Darwin 和 FreeBSD,在 Windows 上是没有办法使用的。因为插件系统的实现基于一些黑魔法,所以跨平台的编译也会遇到一些比较奇葩的问题,作者在使用插件系统时也踩过很多坑,如果对 Go 语言不是特别了解,还是不建议使用该模块的。