Spec-Zone.ru › Go

Пакет plugin

  • import "plugin"
  • Обзор
  • Указатель

Обзор

Пакет plugin реализует загрузку и разрешение символов плагинов Go.

Плагин — это пакет main на Go с экспортируемыми функциями и переменными, который был собран с помощью:

go build -buildmode=plugin

При первом открытии плагина вызываются функции init всех пакетов, которые ещё не являются частью программы. Функция main не запускается. Плагин инициализируется только один раз, и его нельзя закрыть.

Предупреждения

Возможность динамически загружать части приложения во время выполнения, например, на основе конфигурации, заданной пользователем, может быть полезным строительным блоком в некоторых архитектурах. В частности, поскольку приложения и динамически загружаемые функции могут напрямую совместно использовать структуры данных, плагины могут обеспечить очень высокопроизводительную интеграцию отдельных частей.

Однако механизм плагинов имеет ряд существенных недостатков, которые следует тщательно учитывать при проектировании. Например:

  • В настоящее время плагины поддерживаются только в Linux, FreeBSD и macOS, поэтому они не подходят для приложений, предназначенных для переносимого использования.

  • Поддержка плагинов детектором гонок Go ограничена. Даже простые состояния гонки могут не обнаруживаться автоматически. Дополнительную информацию см. на странице https://go.dev/issue/24245.

  • Для приложений, использующих плагины, может потребоваться тщательная настройка, чтобы обеспечить доступность различных частей программы в нужном месте файловой системы (или образа контейнера). Напротив, развернуть приложение, состоящее из одного статического исполняемого файла, просто.

  • Рассуждать об инициализации программы сложнее, если некоторые пакеты могут быть инициализированы лишь спустя долгое время после начала работы приложения.

  • Злоумышленник может воспользоваться ошибками в приложениях, загружающих плагины, чтобы загрузить опасные или недоверенные библиотеки.

  • Вероятны сбои во время выполнения, если все части программы (приложение и все его плагины) не скомпилированы с использованием в точности одной и той же версии цепочки инструментов, одинаковых тегов сборки и одинаковых значений определённых флагов и переменных окружения.

  • Проблемы со сбоями также вероятны, если все общие зависимости приложения и его плагинов не собраны из в точности одного и того же исходного кода.

  • В совокупности эти ограничения означают, что на практике приложение и все его плагины должны собираться одним человеком или компонентом системы. В таком случае этому человеку или компоненту может быть проще сгенерировать исходные файлы Go с пустыми импортами нужного набора плагинов, а затем обычным способом скомпилировать статический исполняемый файл.

По этим причинам многие пользователи считают, что традиционные механизмы межпроцессного взаимодействия (IPC), такие как сокеты, каналы, удалённый вызов процедур (RPC), отображения общей памяти или операции с файловой системой, могут быть более подходящими, несмотря на накладные расходы, связанные с производительностью.

Указатель

  • type Plugin
  • func Open(path string) (*Plugin, error)
  • func (p *Plugin) Lookup(symName string) (Symbol, error)
  • type Symbol

Файлы пакета

plugin.go plugin_dlopen.go

type Plugin 1.8

Plugin — это загруженный плагин Go.

type Plugin struct {
    // contains filtered or unexported fields
}

func Open 1.8

func Open(path string) (*Plugin, error)

Open открывает плагин Go. Если путь уже открывали, возвращается существующий *Plugin. Функцию безопасно вызывать одновременно из нескольких горутин.

func (*Plugin) Lookup 1.8

func (p *Plugin) Lookup(symName string) (Symbol, error)

Lookup ищет в плагине p символ с именем symName. Символом может быть любая экспортируемая переменная или функция. Если символ не найден, возвращается ошибка. Функцию безопасно вызывать одновременно из нескольких горутин.

type Symbol 1.8

Symbol — это указатель на переменную или функцию.

Например, плагин, определённый следующим образом,

package main

import "fmt"

var V int

func F() { fmt.Printf("Hello, number %d\n", V) }

можно загрузить с помощью функции Open, а затем получить доступ к экспортируемым символам пакета V и F

p, err := plugin.Open("plugin_name.so")
if err != nil {
	panic(err)
}
v, err := p.Lookup("V")
if err != nil {
	panic(err)
}
f, err := p.Lookup("F")
if err != nil {
	panic(err)
}
*v.(*int) = 7
f.(func())() // prints "Hello, number 7"
type Symbol any

© Google, Inc.
Licensed under the Creative Commons Attribution License 3.0.
http://golang.org/pkg/plugin/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API