In Node.js konnte ich einen WordPress-Klon relativ einfach mit dem EventEmitter erstellen, um ein Hooks-System in den CMS-Kern zu replizieren und dort zu erstellen, an welches Plugins sich dann anhängen könnte.
Ich benötige nun dasselbe Maß an Erweiterbarkeit und Core-Isolation für mein CMS, das in Go geschrieben und portiert wurde. Im Grunde habe ich den Kern jetzt fertig, aber um es wirklich flexibel zu machen, muss ich in der Lage sein, Ereignisse (Hooks) einzufügen und Plugins mit zusätzlichen Funktionen an diese Hooks anzuhängen.
Ich interessiere mich nicht für die Neukompilierung (dynamisches / statisches Verknüpfen), solange Sie nicht den Kern ändern müssen, um Plugins zu laden - der CMS-Kern sollte niemals modifiziert werden. (wie WP, Drupal etc.)
Ich habe bemerkt, dass es ein paar ziemlich unbekannte Projekte gibt, die versuchen, Ereignisse in Go zu implementieren, die ähnlich aussehen wie EventEmitter in Node.js:
Da diese zwei Projekte oben nicht viel Popularität und Aufmerksamkeit gewonnen haben, denke ich, dass diese Art des Nachdenkens über Ereignisse jetzt so sein könnte, wie wir es in Go machen sollten? Heißt das Go ist vielleicht nicht auf diese Aufgabe ausgerichtet? Um wirklich erweiterbare Anwendungen durch Plugins zu machen?
Scheint nicht so, als ob Go Ereignisse in seinen Kern eingebaut hat, und RPC scheint keine gültige Lösung zu sein, um Plugins in Ihre Kernanwendung zu integrieren, so wie sie nativ integriert sind und als Teil der Hauptanwendung sich selbst.
Was ist der beste Weg für eine nahtlose Plugin-Integration in Ihre Kern-App, für unbegrenzte Erweiterungspunkte (im Kern), ohne den Kern jedes Mal zu manipulieren, wenn Sie ein neues Plugin anschließen müssen?
Im Allgemeinen, in Go, wenn Sie Ereignisse benötigen, müssen Sie wahrscheinlich Kanäle verwenden, aber wenn Sie Plugins benötigen, ist der Weg zu gehen Schnittstellen. Hier ist ein etwas langatmiges Beispiel für eine einfache Plugin-Architektur, die den Code minimiert, der sein muss geschrieben in der Hauptdatei der App, um Plugins hinzuzufügen (dies kann automatisiert werden, aber nicht dnyamic, siehe unten).
Ich hoffe, es ist in der Richtung, nach der Sie suchen.
1. Die Plugin-Schnittstellen
Okay, sagen wir, wir haben zwei Plugins, Fooer und Doer. Wir definieren zuerst ihre Schnittstellen:
%Vor%2. Die Plugin-Registrierung
Jetzt hat unsere Kern-App eine Plugin-Registry. Ich mache hier etwas schnell und schmutzig, nur um die Idee zu vermitteln:
%Vor%Jetzt stellen wir Methoden vor, Plugins zur Registrierung hinzuzufügen. Der einfache Weg ist, einen pro Typ hinzuzufügen, aber Sie könnten gehen mit komplexeren Reflektionen und haben eine Funktion. Aber normalerweise in Go, versuche die Dinge einfach zu halten:)
%Vor%3. Implementierung und Registrierung eines Plugins
Angenommen, dies ist Ihr Plugin-Modul. Wir erstellen ein Plugin, das ein Macher ist, und in unserem Paket
init()
Methode wir registrieren es. init () passiert einmal beim Programmstart für jedes importierte Paket.
Auch hier ist die "init magic", die das Paket automatisch registriert
%Vor%4. Das Importieren der Plugins registriert sie automatisch
Und jetzt müssen wir nur das ändern, was wir in unser Hauptpaket importieren. Schon seit
Go verfügt nicht über dynamische Importe oder Verknüpfungen, dies ist das einzige, was Sie schreiben müssen.
Es ist ziemlich trivial, ein go generate
-Skript zu erstellen, das eine Hauptdatei erzeugt
indem Sie in den Dateibaum oder eine Konfigurationsdatei schauen und alle Plugins finden, die Sie importieren müssen.
Es ist nicht dynamisch, aber es kann automatisiert werden. Da main das Plugin für den Nebeneffekt der Registrierung importiert, verwendet der Import die leere ID, um nicht verwendete Importfehler zu vermeiden .
5. Im Kern der App
Und jetzt braucht unsere Kern-App keinen Code mehr, um mit Plugins interagieren zu können:
%Vor%Und das ist es auch schon. Beachten Sie, dass die Plugin-Registrierung ein separates Paket sein sollte dass sowohl der Kern der App als auch die Plugins importiert werden können, so dass Sie keine zirkulären Importe haben.
Natürlich können Sie Event-Handler zu diesem Mix hinzufügen, aber wie ich gezeigt habe, wird es nicht benötigt.
Tags und Links go extensibility eventemitter plugin-architecture