1// Copyright 2016 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5// Package plugin implements loading and symbol resolution of Go plugins. 6// 7// A plugin is a Go main package with exported functions and variables that 8// has been built with: 9// 10// go build -buildmode=plugin 11// 12// When a plugin is first opened, the init functions of all packages not 13// already part of the program are called. The main function is not run. 14// A plugin is only initialized once, and cannot be closed. 15// 16// # Warnings 17// 18// The ability to dynamically load parts of an application during 19// execution, perhaps based on user-defined configuration, may be a 20// useful building block in some designs. In particular, because 21// applications and dynamically loaded functions can share data 22// structures directly, plugins may enable very high-performance 23// integration of separate parts. 24// 25// However, the plugin mechanism has many significant drawbacks that 26// should be considered carefully during the design. For example: 27// 28// - Plugins are currently supported only on Linux, FreeBSD, and 29// macOS, making them unsuitable for applications intended to be 30// portable. 31// 32// - Applications that use plugins may require careful configuration 33// to ensure that the various parts of the program be made available 34// in the correct location in the file system (or container image). 35// By contrast, deploying an application consisting of a single static 36// executable is straightforward. 37// 38// - Reasoning about program initialization is more difficult when 39// some packages may not be initialized until long after the 40// application has started running. 41// 42// - Bugs in applications that load plugins could be exploited by 43// an attacker to load dangerous or untrusted libraries. 44// 45// - Runtime crashes are likely to occur unless all parts of the 46// program (the application and all its plugins) are compiled 47// using exactly the same version of the toolchain, the same build 48// tags, and the same values of certain flags and environment 49// variables. 50// 51// - Similar crashing problems are likely to arise unless all common 52// dependencies of the application and its plugins are built from 53// exactly the same source code. 54// 55// - Together, these restrictions mean that, in practice, the 56// application and its plugins must all be built together by a 57// single person or component of a system. In that case, it may 58// be simpler for that person or component to generate Go source 59// files that blank-import the desired set of plugins and then 60// compile a static executable in the usual way. 61// 62// For these reasons, many users decide that traditional interprocess 63// communication (IPC) mechanisms such as sockets, pipes, remote 64// procedure call (RPC), shared memory mappings, or file system 65// operations may be more suitable despite the performance overheads. 66package plugin 67 68// Plugin is a loaded Go plugin. 69type Plugin struct { 70 pluginpath string 71 err string // set if plugin failed to load 72 loaded chan struct{} // closed when loaded 73 syms map[string]any 74} 75 76// Open opens a Go plugin. 77// If a path has already been opened, then the existing *[Plugin] is returned. 78// It is safe for concurrent use by multiple goroutines. 79func Open(path string) (*Plugin, error) { 80 return open(path) 81} 82 83// Lookup searches for a symbol named symName in plugin p. 84// A symbol is any exported variable or function. 85// It reports an error if the symbol is not found. 86// It is safe for concurrent use by multiple goroutines. 87func (p *Plugin) Lookup(symName string) (Symbol, error) { 88 return lookup(p, symName) 89} 90 91// A Symbol is a pointer to a variable or function. 92// 93// For example, a plugin defined as 94// 95// package main 96// 97// import "fmt" 98// 99// var V int 100// 101// func F() { fmt.Printf("Hello, number %d\n", V) } 102// 103// may be loaded with the [Open] function and then the exported package 104// symbols V and F can be accessed 105// 106// p, err := plugin.Open("plugin_name.so") 107// if err != nil { 108// panic(err) 109// } 110// v, err := p.Lookup("V") 111// if err != nil { 112// panic(err) 113// } 114// f, err := p.Lookup("F") 115// if err != nil { 116// panic(err) 117// } 118// *v.(*int) = 7 119// f.(func())() // prints "Hello, number 7" 120type Symbol any 121