2013-08-14 18 views
12

Come dice il titolo, voglio caricare in modo dinamico un pacchetto Go (o meno) basato su informazioni disponibili solo in fase di esecuzione.È possibile caricare in modo dinamico Go codice?

L'obiettivo è consentire all'utente di estendere il programma tramite pacchetti personalizzati che aggiungono nuovi comandi di script nativi. Attualmente ogni volta che aggiungo nuovi comandi o non desidero disabilitare alcuni comandi, ho bisogno di modificare il programma e ricompilarlo, mentre se potessi fare una specie di dll o qualcosa di simile allora potrei creare un comando di script "import" per cercare e caricare una libreria di comandi con nome.

Per i curiosi, il programma in questione è una libreria di script basata su comandi personalizzati che utilizzo per tutti i tipi di cose.

Ho fatto qualche ricerca in anticipo, ed i risultati non sembrano buoni, ma non sono riuscito a trovare un chiaro no.

+0

questa sarebbe una cattiva idea. Non vuoi creare di interi pacchetti solo per il comfort –

+1

Non è solo per il comfort, è per permettermi di estendere le estensioni facoltative di offerta per quelli che li vogliono senza doverli dare a tutti. –

+0

I cappelli si sovrappongono per i ragazzi che stanno dicendo "non hai bisogno di questo", basta dare una risposta se ne hai uno. E poi suggerire altro modo. Molte volte, anche se l'autore ha effettivamente bisogno di qualcosa di diverso, molti ragazzi stanno arrivando a questa domanda dalla ricerca, che ha bisogno esattamente di quello. –

risposta

14

Go non supporta ancora le librerie dinamiche. Elias Naur ha recentemente pubblicato alcune patch, ma non sono state ancora esaminate ed è improbabile che vengano incluse in Go 1.2. È possibile leggere le discussioni su Google Gruppi:

Per quanto ne so, che sono le discussioni più recenti su questo argomento.

C'è comunque un altro approccio. È possibile avviare i plug-in in processi separati e utilizzare il pacchetto net/rpc per comunicare con l'app principale. Ciò consente anche di avviare/arrestare/ricompilare dinamicamente plug-in separati e ha il vantaggio che un plug-in non valido non può bloccare il programma. Vai eccelle alla comunicazione di rete, devi solo farne buon uso.

ho bisogno di modificare il programma e ricompilare,

Si può anche non crei un piccolo script che guarda per i cambiamenti nella directory corrente (utilizzando fsnotify) ed esegue "GO costruire" seguito da un riavvio del tuo programma. Uso questo approccio su alcuni dei miei progetti web durante lo sviluppo locale e funziona perfettamente. Non sono in grado di osservare i tempi di compilazione e sono abbastanza veloce nel cambiare e rinfrescare la finestra del browser. Il ciclo di sviluppo My Python, in cui l'interprete deve essere riavviato e tutti i moduli devono essere reimportati ad ogni modifica (e ciò potrebbe richiedere un tempo significativo in progetti più grandi!), Si sente davvero goffo rispetto a Go.

+0

Grazie, sapevo che le DLL non sono supportate, ma ero curioso se qualcuno di nuovo un modo per fingere qualcosa come loro. Sembra che RPC sia la strada da percorrere, la ricompilazione dinamica non funzionerà per una libreria. –

+1

Dopo alcuni test, sembra che rpc non funzioni per quello di cui ho bisogno :(Sembra che un sistema di plugin che usa tutto il codice go sia imposibile così com'è –

+0

Ottima risposta Grazie – Triptych

0

Bene, c'è un dlopen-package for Go - quindi, almeno, puoi caricare la tua libreria condivisa (DLL) nel tuo programma Go adesso ... Probabilmente dovrai codificare la tua estensione in C, C++ o qualcos'altro, per il quale si hanno strumenti in grado di generare librerie condivise.

2

C'è supporto per questo in Go 1.8. Al momento è piuttosto immaturo e rudimentale, ma è finalmente possibile.

Anche il progetto go-bind-plugin di Mateusz Gajewski può essere interessante, in quanto semplifica l'utilizzo di plug-in caricati.

Dalla documentazione plugin package:

Ad esempio, un plugin definito come

package main 

// // No C code needed. 
import "C" 

import "fmt" 

var V int 

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

possono essere caricati con la funzione Open e quindi i simboli pacchetto esportato V e F sono accessibili

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 interface{} 
Problemi correlati