Aller au contenu

go-like comparé aux autres outils ​

Une comparaison juste commence par la responsabilité, pas par une liste de fonctionnalités cochées. NestJS, Fastify, Hono, Elysia, Koa et tRPC résolvent des parties différentes de la stack applicative TypeScript. go-micro et go-kratos sont des références de frameworks Go, avec d'autres choix de transport et de génération de code. go-like est un ensemble de briques TypeScript qui rend explicites le cycle de vie, les appels internes unaires, les contrats de fournisseurs et la composition entre runtimes.

Cette page distingue les niveaux de preuve :

  • Source signifie que le checkout go-like actuel expose l'API ou la frontière indiquée.
  • Externe épinglé signifie que la comparaison utilise la release, le commit ou la documentation officielle consignés dans le registre de recherche. Ce n'est ni un benchmark récent ni une affirmation qu'une branche main non épinglée n'a pas changé.
  • Déclaré signifie qu'un exemple ou une lane de tests existe dans le dépôt. Ce n'est pas un résultat réussi.
  • Lacune signifie que le dépôt actuel ne prouve pas un engagement de compatibilité.

Le baseline source actuel de go-like pour ce parcours est le commit 9385dbf5b6a7d913be56a80ade359e1bf9be8675. Le relevé de recherche local contient une divergence de commit pour go-micro : une fiche de comparaison cite 9d306dcfc1a912a8a9493f31fee0bb983475258d, tandis que le mémo détaillé sur une version fixe a inspecté go-micro v6.9.0 au commit 3c39d17fadaa9ec21b671be4afef3e63846406e6. Considérez ces valeurs comme des entrées de comparaison à revérifier, et non comme une garantie actuelle de l'upstream.

Place dans la stack ​

OutilProblème principalCe qu'il prend généralement en chargeCe que go-like peut compléter, sans le remplacer
NestJSFramework d'application Node fondé sur des conventionsModules, providers, controllers, decorators, application context, cycle de vie du framework, adaptateur HTTP ou microservicesUne frontière de cycle de vie structurelle ou un contrat d'appel interne autour d'une application native, si un pont explicite est écrit
FastifyServeur HTTP Node et pipeline de requêtesTable de routes, hooks, plugins, encapsulation, listener Node, objets request/replyUn adaptateur de cycle de vie ou de fournisseur autour d'une ressource dont Fastify est propriétaire
HonoRoutage et middleware fondés sur les Web StandardsRoutes, middleware, sous-applications, app.fetch, choix de l'adaptateur de runtimeCore App, cycle de vie explicite des ressources, Client/Transport interne, découverte
ElysiaFramework Web typé centré sur BunArbre de routes, composition de schémas, decorators, hooks, adaptateur Bun ou Web StandardBriques de cycle de vie Core et services internes, tout en conservant le comportement natif d'Elysia
KoaNoyau minimal de middleware NodePile de middleware et listener Node ; le routeur est généralement externeCycle de vie et contrats de services internes sans introduire un autre routeur
tRPCCouche de procédures typéesChemins de router/procedure, parseurs d'entrée/sortie, context factory, adaptateurs HTTP/Fetch/WSPropriété des fournisseurs, politique de découverte, cycle de vie explicite de l'App
go-microÉcosystème Go orienté microservices et agentsGo Context, abstractions service/client/transport/registry/broker, écosystème de fournisseurs et périmètre supplémentaire agent/flow/MCP/A2Ago-like reprend une partie du vocabulaire, pas l'ABI Go, les goroutines ni la compatibilité des transports
go-kratosFramework Go pour services cloud-nativeCycle de vie App, Go Context, transports HTTP/gRPC, middleware, registry, config, génération de code ProtobufCode Context-first sur Protobuf-ES; gRPC standard avec quatre cardinalités via /native
go-likeBriques explicites pour services TypeScriptContext, cycle de vie App/Server, bordure Fetch standard, transport interne Fetch JSON et SSE, Client/Server, Registry/Discovery/Selector, Config/Store/Cache/Broker/Health, adaptateursL'application reste propriétaire de ses routes, de ses plans de données natifs, de sa policy métier, de l'auth et du déploiement

Le projet n'essaie donc pas de gagner un concours du « plus gros framework ». La vraie question est de savoir si une application a besoin de rendre ces frontières explicites et composables.

Matrice des responsabilités ​

PréoccupationNestJSFastifyHono / Elysia / KoatRPCgo-like
Table de routes externeControllers et decoratorsInstance FastifyInstance du framework ou routeur externeRouter de procédures, pas des routes REST ordinairesFramework externe ou application
ABI du handler WebAbstraction request/reply du frameworkrequest/reply NodeFetch standard au centre pour Hono et les adaptateurs Web StandardAdaptateurs Fetch/Node/Express/Fastify(Request) => Response | Promise<Response>
Cycle de vie de l'applicationApplication context et hooksready, listen, close, hooksL'adaptateur de runtime et le framework varientResponsabilité du host/de l'adaptateurnewApp, App.run, App.stop, hooks, Servers structurels
Cycle de vie des ressourcesHooks du container/frameworkHooks de plugin et de serveurResponsabilité de l'application/runtimeResponsabilité de l'application/adaptateurContrats explicites Server.start(ctx) / stop(ctx) et propriété de l'adaptateur
Composition des dépendancesContainer/providers NestDecoration et encapsulation des pluginsContext/env et composition ; pas de conteneur DI généralContext factory explicite et composition du routerConstructeurs explicites et functional options ; pas de conteneur DI
Transport interneTransports microservices et adaptateurs frameworkPas une abstraction de découverte de servicesPas une abstraction de découverte de servicesAdaptateurs de procédures et WebSocket optionnelTransport, Client, Listener, defineService, SSE ServerStream
Découverte et sélectionSpécifiques au transport ou externesExternesExternesExternesRegistry, Discovery, Watcher, Filters, cinq policies de Selector
RetrySpécifique au framework ou fournisseurSpécifique à l'application/pluginSpécifique à l'applicationSpécifique au middleware/adaptateurUne tentative par défaut ; withRetry exige une autorisation et un total de tentatives
StreamingChoix du framework/fournisseurChoix des streams Node/WebWeb Streams natives et API du frameworkDépend de l'adaptateur HTTP/WSWeb Streams; JSON or SSE server stream; Fetch unary/server-streaming; /native client-streaming/bidi
Instrumentation globaleIntégration framework/fournisseurÉcosystème de pluginsÉcosystème de middlewareMiddleware/adaptateursWrappers explicites ; aucune installation de fournisseurs globaux

Les libellés des cinq premières lignes décrivent des positions d'architecture, pas un classement de qualité. Lorsqu'un framework possède la table de routes, c'est utile si la composition des routes est le problème à résoudre. C'est simplement un choix de responsabilité différent de celui de go-like, qui laisse les routes à l'application.

Cycle de vie et Context ​

Le code source actuel de go-like définit :

ts
interface Server {
  start(ctx: Context): Promise<void>
  stop(ctx: Context): Promise<void>
}

interface App {
  run(): Promise<void>
  stop(): Promise<void>
}

Le contrat Server est structurel. Un worker natif, un listener, un scheduler, une souscription de broker, une destination de logs ou un fournisseur de télémétrie peut rejoindre Core si un adaptateur sait décrire honnêtement son admission et son état terminal.

Le Context de go-like est lui aussi structurel et utilise AbortSignal en interne. Il expose deadline(), done(), err() et value(key), avec des constructeurs tels que background, withCancel, withCancelCause, withTimeout, withDeadline, withoutCancel et withValue.

Cela rappelle le style explicite de Go où le Context est le premier argument, mais ce n'est pas compatible au niveau ABI avec context.Context. Context ne fournit ni goroutines, ni channels, ni API gRPC. La bonne question de migration est « où l'annulation et la propriété franchissent-elles cette frontière ? », et non « quel nom de type est identique ? ».

Core ne promet pas un arrêt dans l'ordre inverse pour les Servers frères. Il appelle les stop(ctx) frères en parallèle, puis attend les Promises start terminales et agrège les échecs. Un application context Nest, un graphe de plugins Fastify, le cycle de vie Elysia ou un adaptateur de host peuvent avoir un ordre et une sémantique terminale différents. Comparez le véritable propriétaire, pas seulement l'étiquette « graceful ».

Transport et appels de service ​

La chaîne d'appel interne de go-like est volontairement décomposée :

text
Client
  -> Discovery snapshot, optional
  -> ordered Filter callbacks, optional
  -> Selector.select
  -> opaque ServiceEndpoint URL
  -> Transport.dial or resident logical owner
  -> fetch(Request)
  -> @go-like/server route and unary handler
  -> read Response
  -> feedback and owner release

Un Endpoint typé associe la validation Struct des requêtes et réponses à un corps JSON Fetch. Ce n'est ni un IDL ni un protocole généré. withEndpoint(...) sélectionne un instantané direct à la construction ; les instantanés directs et découverts utilisent le même Selector. Le chemin Memory Transport en processus reste un bon premier test.

Les options de transport microservices de NestJS, les adaptateurs de procédures tRPC et les transports des frameworks Go ne sont pas interchangeables avec ce DAG. Ils peuvent avoir une autre identité de route, un autre modèle de sérialisation, un autre pool de connexions ou une autre couche de retry. Une comparaison doit noter ces différences plutôt que cocher comme équivalentes toutes les cases « RPC ».

Périmètre du retry et du streaming ​

La différence négative la plus importante concerne les sémantiques :

  • Les appels go-like font exactement une tentative par défaut.
  • withRetry(...) exige authorization: "idempotent" | "caller-approved", un maxAttempts positif et shouldRetry.
  • L'autorisation est une déclaration du caller, pas une preuve d'idempotence.
  • Un retry peut sélectionner un nouvel endpoint, car chaque tentative repasse par la découverte et la sélection.
  • Une réponse déjà reçue, mais suivie d'un échec de feedback ou de nettoyage, n'est pas rejouée.

La recherche comparative Go relève d'autres valeurs par défaut et capacités : DefaultRetries de go-micro ne signifie pas simplement « cinq requêtes au total », car la limite de sa boucle peut produire six itérations lorsque l'autorisation de retry reste vraie ; sa forme de stream publique et son implémentation par défaut de CloseSend varient également selon le fournisseur. go-kratos combine génération Protobuf/gRPC et formes de streaming HTTP, où SSE et WebSocket ont des directions et des comportements de fermeture différents. Ce sont des choix de fournisseur et d'architecture, pas des options go-like manquantes.

Pour go-like :

text
Web framework or Fetch Handler
  -> Web Streams, SSE, or WebSocket behavior owned by the application/framework

go-like internal Client/Transport
  -> one JSON body, or one SSE server stream when `stream: true`
  -> not a bidirectional multi-frame protocol

@go-like/transport-grpc-buf
  -> Fetch: Connect/gRPC-Web unary and server-streaming
  -> /native: standard gRPC unary, server-streaming, client-streaming, bidi

Un ReadableStream Web n'est pas un canal RPC interne. Ne comparez pas un corps HTTP en streaming avec un transport send/recv à plusieurs frames comme s'il s'agissait de la même fonctionnalité.

Comparaison des runtimes ​

Question de runtimePreuve go-likeConséquence pour la comparaison
Le code partagé peut-il utiliser Fetch et AbortSignal ?Le Web root et les fournisseurs Config/Transport sélectionnés utilisent des Web APIs standard ou un Fetch injectéDes objectifs de portabilité similaires sont possibles, mais les types ne simulent pas le comportement du runtime
Fetch peut-il transporter partout PEM TLS, mTLS, ALPN et HTTP/2 ?Le sous-chemin Transport Node possède le comportement natif ; le chemin Fetch root n'expose pas tous les contrôlesComparez les capacités du host et les chemins d'import, pas seulement les noms de paquets
L'application conserve-t-elle le routeur du framework ?Les exemples Hono, Elysia et H3 transmettent des handlers Fetch natifsgo-like complète la responsabilité de routage du framework
La version d'un paquet prouve-t-elle sa publication ?workspace:*, 0.0.1N'en déduisez ni disponibilité npm ni maturité de l'écosystème

Le dépôt actuel contient des exemples directs pour Hono, Elysia, H3 et Fetch sans framework. Il ne contient ni pont NestJS ou Fastify actuel, ni suite de compatibilité. Ce sont des publics de migration, pas des intégrations directes prises en charge.

Comparaison détaillée par outil ​

NestJS ​

NestJS est un framework d'application fondé sur des conventions. Ses modules, providers, controllers, decorators, interceptors, pipes et hooks d'application forment un conteneur et un modèle de requête cohérents. go-like ne fournit ni conteneur de modules compatible avec Nest, ni pont pour controllers.

Une frontière d'intégration raisonnable est un adaptateur appartenant à l'application, qui implémente le Server structurel de go-like autour d'une application Nest ou de son host. L'adaptateur devrait définir à quel moment Nest a admis le listener, comment stop(ctx) se traduit par la fermeture de Nest et ce qui se passe après un timeout. Le dépôt actuel ne prouve pas l'existence d'un tel pont ; la documentation ne doit donc pas montrer un appel direct comme newNodeServer(nestApp, ...).

Fastify ​

Fastify possède une table de routes, l'encapsulation des plugins, des hooks et un listener Node. Son graphe de plugins est un bon point de comparaison pour les scopes de dépendances, mais decorate n'est pas un conteneur général de providers comme celui de Nest. go-like ne convertit pas automatiquement l'ABI request/reply de Fastify en Fetch Handler, et aucun pont Fastify actuel n'est testé dans le dépôt.

Gardez routes et plugins Fastify natifs. Si vous adoptez go-like, écrivez un Server structurel explicite autour du propriétaire Fastify ou exposez une frontière Fetch implémentée séparément. N'appelez ni l'injection de requête ni l'arrêt natif de Fastify un contrat go-like de Transport ou de Client.

Hono ​

Hono est le complément le plus clairement démontré. L'exemple actuel crée les routes dans Hono, transmet app.fetch à newNodeServer et place ce host dans une Core App. Hono reste propriétaire des routes et du middleware ; go-like possède la frontière de cycle de vie du host lorsque l'application le choisit.

Elysia ​

Elysia fournit un modèle de composition de routes et de schémas centré sur Bun et expose aussi un handler Web Standard dans le chemin d'adaptateur concerné. Conservez l'arbre de routes, les decorators, derives, hooks, streams et le comportement spécifique à Bun d'Elysia. go-like peut posséder l'App et une frontière explicite de ressource, mais ne transforme pas .listen() en API go-like inter-runtime.

Koa ​

Koa est un petit noyau de middleware Node qui n'embarque pas de routeur. C'est un bon exemple de framework qui laisse volontairement davantage de composition à l'application, en dehors du core. go-like ne doit pas combler ce vide en ajoutant un routeur. Gardez le middleware Koa et tout routeur externe natifs, puis ajoutez une frontière de cycle de vie ou d'appel interne uniquement là où elle est nécessaire.

tRPC ​

tRPC possède un router de procédures typées et son middleware de procédures. Il peut utiliser des adaptateurs Fetch, Node, Express, Fastify ou WebSocket, mais ce n'est ni un Registry, ni un Selector, ni un pool de connexions, ni un gestionnaire du cycle de vie applicatif. L'Endpoint typé de go-like est une liaison runtime Struct plus petite sur des corps JSON Fetch, pas un DSL de procédures ni un IDL généré concurrent de tRPC.

go-micro et go-kratos ​

Ces projets Go sont des références d'architecture utiles pour les appels Context-first, le cycle de vie des services, Registry, Discovery, Selector et le vocabulaire des transports. Ils ne sont pas des cibles de compatibilité :

  • context.Context de Go et Context de go-like partagent l'intention d'une annulation explicite, mais leurs représentations runtime diffèrent.
  • Le modèle de watcher Registry de go-micro et les snapshots de remplacement complet de go-like ne doivent pas être présentés comme des flux d'événements identiques.
  • @go-like/protoc-gen-like génère le code Protobuf RPC avec Context en premier argument, sur Protobuf-ES. @go-like/transport-grpc-buf fournit unary et server-streaming Connect/gRPC-Web via Fetch ; /native ajoute gRPC standard avec les quatre cardinalités, dont client-streaming et bidi. Ce chemin est indépendant du chemin interne Fetch/SSE.
  • Les valeurs par défaut des fournisseurs go-micro et go-kratos, les boucles de retry, le half-close des streams et les sélecteurs par défaut dépendent de la version. Utilisez la table des commits upstream épinglés dans le relevé de recherche et revérifiez-la avant de publier une nouvelle comparaison.

Que choisir ? ​

Si votre problème principal est...Commencez avec...Ajoutez go-like lorsque...
Controllers, modules, decorators et DINestJSvous avez besoin d'une frontière explicite autour d'une ressource existante ou d'un appel interne, et acceptez d'écrire l'adaptateur
Routes HTTP Node, hooks et encapsulation de pluginsFastifyvous avez besoin d'une composition de cycle de vie au-delà du host ou de contrats de services internes
Routes Web Standards entre runtimesHonovous avez besoin du cycle de vie App/Server, d'appels internes ou de propriété des fournisseurs
Composition de schémas et routes centrée sur BunElysiavous avez besoin de frontières explicites de cycle de vie et de transport tout en gardant Elysia
Middleware Node minimalKoa et un routeuril vous manque le contrat de cycle de vie ou d'appel interne, pas un autre routeur
Procédures typéestRPCvous avez aussi besoin de découverte explicite, de propriété des fournisseurs ou d'un cycle de vie Core
Stack de microservices Gogo-micro ou go-kratosvous construisez une composition TypeScript séparée, et non un port compatible au niveau du source
Briques de services TypeScript inter-runtimego-likeutilisez uniquement les paquets et fournisseurs qui résolvent la frontière voulue

La bonne réponse peut être d'utiliser les deux systèmes. go-like est le plus utile lorsque son modèle de propriété explicite supprime une ambiguïté réelle ; ajouter tous ses paquets à une application déjà complète avec un autre framework irait à l'encontre de l'objectif de petites briques.

Ancrages de preuve ​

Les affirmations go-like de cette page peuvent être retracées dans l'arbre actuel et les entrypoints de paquets :

  • README.md pour le périmètre du produit et ses exclusions explicites ;
  • packages/core/src/app.ts pour App, Server, le démarrage, l'arrêt et le comportement des timeouts ;
  • packages/web/src/context.ts pour le Handler standard et le pont Context ;
  • packages/client/src/index.ts pour les options du Client, le pooling, le retry et le pipeline des tentatives ;
  • packages/server/src/index.ts pour les handlers internes unaires et le dispatch des routes ;
  • packages/transport/src/types.ts et packages/transport/src/endpoint.ts pour les frontières Fetch Request/Response et defineService ;
  • packages/registry/src/types.ts et packages/registry/src/selector.ts pour les snapshots, filtres, sélecteurs et feedback.

Le relevé de recherche conserve également ces entrées de comparaison externes épinglées :

Ces URL sont des références de comparaison, pas une affirmation que cette phase de documentation a téléchargé ou revérifié chaque page upstream. Revérifiez les tags de release ou les commits avant de modifier une affirmation sensible à la version.