Go Academy · Урок

Динамическая загрузка и символы

Загрузка плагинов во время выполнения и вызов экспортируемых символов

Урок 3 из 412 шагов

«Динамическая загрузка и символы» — бесплатный урок Go Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Go Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Go Academy содержит 4 уроков всего.

plugin.Open

plugin.Open(path) загружает скомпилированный файл .so. Функции init() и переменные уровня пакета плагина инициализируются, после чего символы становятся доступными.

p, err := plugin.Open("./plugins/mymodule.so")
if err != nil { log.Fatalf("load: %v", err) }

p.Lookup

p.Lookup(name) находит экспортируемый символ по имени. Он возвращает значение произвольного типа; приведите его к ожидаемому типу.

sym, err := p.Lookup("NewProcessor")
if err != nil { log.Fatalf("lookup: %v", err) }
fn, ok := sym.(func() Processor)
if !ok { log.Fatal("wrong type") }

Загрузка нескольких плагинов

Загрузите каждый файл .so из каталога и зарегистрируйте его в цикле:

entries, _ := os.ReadDir("./plugins")
for _, e := range entries {
    if !strings.HasSuffix(e.Name(), ".so") { continue }
    p, err := plugin.Open("./plugins/" + e.Name())
    if err != nil { log.Printf("skip %s: %v", e.Name(), err); continue }
    loadPlugin(p)
}

Шаблон фабричной функции

Плагины экспортируют фабричную функцию (NewXxx() Processor), а не значение, поэтому хост получает новый экземпляр при каждом вызове:

sym, _ := p.Lookup("NewProcessor")
factory := sym.(func() Processor)
proc := factory() // new instance

Обработка ошибок при поиске

Ошибки Lookup означают, что символ не экспортирован или указано неправильное имя. Обрабатывайте их корректно: пропустите плагин либо запишите ошибку и продолжите загрузку остальных.

plugin.Open идемпотентен

Двойной вызов plugin.Open для одного и того же пути возвращает один и тот же плагин. Плагин инициализируется только один раз.

Отложенная загрузка

Загружайте плагины по требованию, при первом использовании, а не при запуске, чтобы сократить время запуска. Используйте sync.Once для каждого плагина, чтобы гарантировать его загрузку ровно один раз.

var mu sync.Mutex
var loaded = map[string]*plugin.Plugin{}

func getPlugin(path string) (*plugin.Plugin, error) {
    mu.Lock(); defer mu.Unlock()
    if p, ok := loaded[path]; ok { return p, nil }
    p, err := plugin.Open(path)
    if err != nil { return nil, err }
    loaded[path] = p
    return p, nil
}

Соглашения об именовании символов

Используйте имена в формате CamelCase с заглавной буквы для экспортируемых символов — действует правило видимости Go. Распространённое соглашение: Plugin для основного значения или New для фабрики.

Обработка паник плагинов

Если плагин вызывает панику, промежуточное ПО восстановления в хосте может её перехватить, но горутины плагина могут оказаться в неопределённом состоянии. Запишите ошибку и пропустите плагин; не повторяйте попытку.

Проверка метаданных плагина

После загрузки проверьте символ метаданных (например, PluginVersion string), чтобы проверить совместимость до регистрации:

ver, _ := p.Lookup("PluginVersion")
if *ver.(*string) != expectedVersion { log.Fatal("incompatible") }

Быстрая проверка

Что произойдёт, если дважды вызвать plugin.Open с одним и тем же путём?

Итоги: динамическая загрузка и символы

Ключевые моменты:

  • plugin.Open загружает .so; p.Lookup возвращает значение произвольного типа → выполните приведение типа
  • Загружайте плагины из каталога в цикле, чтобы создать систему плагинов
  • plugin.Open идемпотентен; init() выполняется один раз для каждого пути
  • Для получения новых экземпляров предпочтительнее фабричные функции, а не символы-значения
Можно начать бесплатно

Изучай Go с ИИ-репетитором — бесплатно

Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.

Курсы
51
Уроки
203

Часто задаваемые вопросы

Урок «Динамическая загрузка и символы» бесплатный?

Да — полный текст урока «Динамическая загрузка и символы» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Go Academy, подпишись на CoddyKit PRO. Курс Go Academy содержит 4 уроков всего.

Чему я научусь в уроке «Динамическая загрузка и символы»?

Загрузка плагинов во время выполнения и вызов экспортируемых символов Ты практикуешь Go Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Go Academy?

Предыдущий опыт не требуется. Go Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.

Сколько времени занимает урок «Динамическая загрузка и символы»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Go Academy?

Да. Каждый урок Go Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Основы пакета plugin в Go
  2. Проектирование интерфейса плагина
  3. Динамическая загрузка и символы
  4. Альтернативы: HashiCorp go-plugin
← Назад к Go Academy