Saltar al contenido

go-like frente a otras herramientas ​

Una comparación justa empieza por la propiedad, no por una lista de casillas de funcionalidades. NestJS, Fastify, Hono, Elysia, Koa y tRPC resuelven partes distintas del stack de aplicaciones TypeScript. go-micro y go-kratos son referencias de frameworks Go con decisiones diferentes sobre transporte y generación de código. go-like es un conjunto de piezas para TypeScript que hace explícitos el ciclo de vida, las llamadas internas unary, los contratos de providers y la composición entre runtimes.

Esta página separa los niveles de evidencia:

  • Source significa que el checkout actual de go-like expone la API o frontera indicada.
  • Pinned external significa que la comparación usa la release, commit o documentación oficial registrada en el research ledger. No es un benchmark nuevo ni una afirmación de que una rama main no fijada siga igual.
  • Declared significa que existe un ejemplo o una lane de pruebas en el repositorio. No es un resultado aprobado.
  • Gap significa que el repositorio actual no demuestra un compromiso de compatibilidad.

El baseline de source actual de go-like para esta guía es el commit 9385dbf5b6a7d913be56a80ade359e1bf9be8675. El registro de investigación local contiene una discrepancia de commit para go-micro: un registro de comparación menciona 9d306dcfc1a912a8a9493f31fee0bb983475258d, mientras que el memo detallado de versión fija inspeccionó go-micro v6.9.0 en 3c39d17fadaa9ec21b671be4afef3e63846406e6. Trátalos como entradas de comparación que deben volver a comprobarse, no como una garantía actual de upstream.

Lugar en el stack ​

HerramientaProblema principalQué suele controlarQué complementaría go-like, sin reemplazarlo
NestJSFramework de aplicaciones Node guiado por convencionesModules, providers, controllers, decorators, application context, ciclo de vida del framework, adaptador HTTP o de microserviciosUna frontera estructural de ciclo de vida o un contrato de llamada interna alrededor de una aplicación nativa, si se escribe un bridge explícito
FastifyServidor HTTP Node y pipeline de requestsTabla de rutas, hooks, plugins, encapsulation, listener de Node, objetos request/replyUn adaptador de ciclo de vida o de provider alrededor de un recurso que pertenece a Fastify
HonoRouting y middleware basados en Web StandardsRoutes, middleware, sub-apps, app.fetch, elección del adaptador de runtimeCore App, ciclo de vida explícito de recursos, Client/Transport internos, discovery
ElysiaFramework Web tipado, centrado en BunRoute tree, schema composition, decorators, hooks, adaptador Bun o Web StandardPiezas de ciclo de vida de Core y servicios internos, conservando el comportamiento nativo de Elysia
KoaKernel mínimo de middleware NodeStack de middleware y listener Node; el router normalmente es externoCiclo de vida y contratos de servicios internos sin introducir otro router
tRPCCapa de procedimientos con tipos segurosRutas de router/procedure, parsers de entrada/salida, context factory, adaptadores HTTP/Fetch/WSPropiedad de providers, policy de discovery y ciclo de vida explícito de App
go-microEcosistema Go orientado a microservicios y agentesGo Context, abstracciones de service/client/transport/registry/broker, ecosistema de providers y alcance adicional de agent/flow/MCP/A2Ago-like toma parte del vocabulario, no el ABI de Go, las goroutines ni la compatibilidad de transportes
go-kratosFramework Go para servicios cloud-nativeCiclo de vida de App, Go Context, transportes HTTP/gRPC, middleware, registry, config, generación de código ProtobufCódigo Context-first sobre Protobuf-ES; gRPC estándar con cuatro cardinalidades mediante /native
go-likePiezas explícitas para servicios TypeScriptContext, ciclo de vida App/Server, borde Fetch estándar, transporte interno unary con Message, Client/Server, Registry/Discovery/Selector, Config/Store/Cache/Broker/Health, adaptadoresLa aplicación sigue siendo responsable de las rutas del framework, planos de datos nativos, policy de negocio, auth y despliegue

Por eso el proyecto no intenta ganar una comparación de “framework más grande”. La pregunta es si una aplicación necesita que estas fronteras sean explícitas y componibles.

Matriz de propiedad ​

PreocupaciónNestJSFastifyHono / Elysia / KoatRPCgo-like
Tabla de rutas externasControllers y decoratorsInstancia de FastifyInstancia del framework o router externoRouter de procedures, no rutas REST ordinariasFramework externo o la aplicación
ABI del handler WebAbstracción request/reply propiedad del adaptadorrequest/reply de NodeFetch estándar como centro en Hono y adaptadores Web StandardAdaptadores Fetch/Node/Express/Fastify(Request) => Response | Promise<Response> estándar
Ciclo de vida de la aplicaciónApplication context y hooksready, listen, close, hooksEl adaptador de runtime y el ciclo de vida del framework varíanResponsabilidad del host/adaptadornewApp, App.run, App.stop, hooks, Servers estructurales
Ciclo de vida de recursosHooks del container/frameworkHooks de plugin y serverResponsabilidad de la aplicación/runtimeResponsabilidad de la aplicación/adaptadorContratos explícitos Server.start(ctx) / stop(ctx) y ownership del adaptador
Composición de dependenciasContainer/providers de NestDecoration y encapsulation de pluginsContext/env y composición; no hay un container DI generalContext factory explícito y composición del routerConstructores explícitos y functional options; no hay container DI
Transporte internoTransportes de microservicios y adaptadores del frameworkNo es una abstracción de discovery de serviciosNo es una abstracción de discovery de serviciosAdaptadores de procedures y WebSocket opcionalTransport, Client, Listener, defineService, SSE ServerStream
Discovery y selecciónEspecíficos del transporte o externosExternosExternosExternosRegistry, Discovery, Watcher, Filters, cinco policies de Selector
RetryEspecífico del framework o providerEspecífico de la aplicación/pluginEspecífico de la aplicaciónEspecífico de middleware/adaptadorUna sola tentativa por defecto; withRetry requiere autorización y total de intentos
StreamingOpciones de framework/providerOpciones de streams Node/WebWeb Streams nativas y APIs del frameworkDepende del adaptador HTTP/WSWeb Streams; JSON or SSE server stream; Fetch unary/server-streaming; /native client-streaming/bidi
Instrumentación globalIntegración de framework/providerEcosistema de pluginsEcosistema de middlewareMiddleware/adaptadoresWrappers explícitos; no instala providers globales

Las etiquetas de las primeras cinco filas describen posiciones arquitectónicas, no una clasificación de calidad. Que un framework sea dueño de una tabla de rutas es útil cuando ese es el problema de composición. Simplemente es una decisión de propiedad distinta de la que toma go-like al dejar las rutas en la aplicación.

Ciclo de vida y Context ​

El source actual de go-like define:

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

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

El contrato Server es estructural. Un worker nativo, listener, scheduler, suscripción a un broker, destino de logs o proveedor de telemetría puede entrar en Core si un adaptador puede describir honestamente la admisión y el comportamiento terminal.

go-like Context también es estructural y usa AbortSignal internamente. Expone deadline(), done(), err() y value(key), con constructores como background, withCancel, withCancelCause, withTimeout, withDeadline, withoutCancel y withValue.

Esto se parece al estilo explícito de Context primero de Go, pero no es compatible a nivel de ABI con context.Context. Context no ofrece goroutines, channels ni una API gRPC. La pregunta correcta para migrar es “¿dónde cruza la cancelación y la propiedad esta frontera?”, no “¿qué nombre de tipo es idéntico?”.

Core no promete un apagado en orden inverso para Servers hermanos. Invoca de forma concurrente las llamadas stop(ctx) de los hermanos, después espera las Promises terminales de start y agrega los fallos. Un application context de Nest, un grafo de plugins de Fastify, el ciclo de vida de Elysia o un adaptador de host pueden tener otro orden y otra semántica terminal. Compara el responsable real, no la etiqueta “graceful”.

Transporte y llamadas de servicio ​

La cadena de llamadas internas de go-like está separada de forma deliberada:

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 tipado vincula la validación de request y response de Struct con un cuerpo JSON de Fetch. No es un IDL ni un protocolo generado. withEndpoint(...) selecciona una instantánea directa durante la construcción; las instantáneas directas y descubiertas usan el mismo Selector. La ruta en proceso con Memory Transport sigue siendo una buena primera prueba.

Las opciones de transporte de microservicios de NestJS, los adaptadores de procedures de tRPC y los transportes de frameworks Go no son intercambiables con este DAG. Pueden tener otra identidad de ruta, modelo de serialización, pool de conexiones o capa de retry. Una comparación debe registrar esas diferencias en lugar de marcar como iguales todas las casillas de “RPC”.

Alcance de retry y streaming ​

La comparación negativa más importante tiene que ver con las semánticas:

  • Las llamadas de go-like hacen exactamente una tentativa por defecto.
  • withRetry(...) requiere authorization: "idempotent" | "caller-approved", un maxAttempts positivo y shouldRetry.
  • La autorización es una declaración del caller, no una prueba de idempotencia.
  • Un retry puede seleccionar otro endpoint porque cada tentativa vuelve a entrar en discovery y selección.
  • Una response que ya se recibió pero después queda seguida por un fallo de feedback o cleanup no se repite.

La investigación de comparación con Go registra defaults y capacidades diferentes: DefaultRetries de go-micro no es una afirmación simple de “cinco requests en total”, porque el límite de su loop puede producir seis iteraciones cuando la autorización del retry sigue siendo verdadera; su forma pública de stream y la implementación default de CloseSend también varían según el provider. go-kratos combina generación de Protobuf/gRPC con formas de streaming HTTP, donde SSE y WebSocket tienen direcciones y comportamientos de cierre distintos. Esas son decisiones del provider y de la arquitectura, no flags de go-like que falten.

Para 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 no es un canal RPC interno. No compares un body HTTP en streaming con un transporte de varios frames send/recv como si fueran la misma funcionalidad.

Comparación de runtimes ​

Pregunta de runtimeEvidencia de go-likeConsecuencia para la comparación
¿El código compartido puede usar Fetch y AbortSignal?Web root y los providers seleccionados de transport/config usan Web APIs estándar o Fetch inyectadoSe pueden tener objetivos de portabilidad parecidos, pero los tipos no hacen polyfill del comportamiento del runtime
¿Fetch puede transportar PEM TLS personalizado, mTLS, ALPN y HTTP/2 de forma portable?El subpath de transporte de Node controla el comportamiento nativo; la ruta Fetch root no expone todos los controlesCompara capacidades del host y rutas de import, no solo nombres de paquetes
¿La aplicación conserva el router del framework?Los ejemplos de Hono, Elysia y H3 pasan handlers Fetch nativosgo-like complementa la propiedad de rutas del framework
¿La versión del paquete demuestra que está publicado?workspace:*, 0.0.1No hagas afirmaciones de disponibilidad en npm o madurez del ecosistema

El repositorio actual contiene ejemplos directos para Hono, Elysia, H3 y Fetch sin framework. No contiene un bridge actual de NestJS o Fastify ni una suite de compatibilidad. Son audiencias de migración, no integraciones directas soportadas.

Comparación detallada por herramienta ​

NestJS ​

NestJS es un framework de aplicaciones guiado por convenciones. Sus modules, providers, controllers, decorators, interceptors, pipes y hooks de aplicación forman un container y un modelo de requests coherentes. go-like no proporciona un container de modules compatible con Nest ni un bridge de controllers.

Una frontera de integración sensata es un adaptador propiedad de la aplicación que implemente el Server estructural de go-like alrededor de una aplicación o host Nest. El adaptador tendría que definir cuándo Nest admitió el listener, cómo se traduce stop(ctx) al cierre de Nest y qué ocurre después de un timeout. El repositorio actual no demuestra ese bridge, así que la documentación no debe mostrar una llamada directa como newNodeServer(nestApp, ...).

Fastify ​

Fastify controla una tabla de rutas, encapsulation de plugins, hooks y un listener Node. Su grafo de plugins sirve para comparar el scope de dependencias, pero decorate no es un container general de providers al estilo Nest. go-like no convierte automáticamente el ABI request/reply de Fastify en un Fetch Handler, y el repositorio actual no prueba ningún bridge de Fastify.

Conserva nativos las rutas y plugins de Fastify. Si adoptas go-like, escribe un Server estructural explícito alrededor del responsable Fastify o expón una frontera Fetch implementada por separado. No llames al request injection ni al shutdown nativo de Fastify un contrato go-like de Transport o Client.

Hono ​

Hono es el complemento demostrado con mayor claridad. El ejemplo actual crea las rutas en Hono, pasa app.fetch a newNodeServer y pone ese host dentro de una Core App. Hono conserva la propiedad de las rutas y del middleware; go-like controla la frontera de ciclo de vida del host cuando la aplicación lo elige.

Elysia ​

Elysia ofrece un modelo de composición de rutas y schemas centrado en Bun, y también expone un handler Web Standard en la ruta de adaptador correspondiente. Conserva nativos el route tree, decorators, derives, hooks, streams y el comportamiento específico de Bun de Elysia. go-like puede controlar la App y una frontera explícita de recursos, pero no convierte .listen() en una API de go-like para todos los runtimes.

Koa ​

Koa es un kernel pequeño de middleware para Node y no incluye un router. Es un buen ejemplo de framework que deja intencionalmente una mayor parte de la composición de la aplicación fuera del core. go-like no debería llenar ese espacio añadiendo un router. Conserva nativos el middleware de Koa y cualquier router externo, y añade una frontera de ciclo de vida o de llamada interna solo donde haga falta.

tRPC ​

tRPC controla un router de procedures tipado y su middleware de procedures. Puede usar adaptadores Fetch, Node, Express, Fastify o WebSocket, pero no es un Registry, Selector, pool de conexiones ni gestor del ciclo de vida de la aplicación. El Endpoint tipado de go-like es un binding runtime más pequeño de Struct sobre un cuerpo JSON de Fetch, no un DSL de procedures ni un IDL generado que compita con tRPC.

go-micro y go-kratos ​

Estos proyectos Go son referencias arquitectónicas útiles para llamadas Context-first, ciclo de vida de servicios, Registry, Discovery, Selector y vocabulario de transportes. No son objetivos de compatibilidad:

  • Go context.Context y go-like Context comparten la intención de cancelación explícita, pero tienen representaciones runtime distintas.
  • El modelo de watchers de Registry de go-micro y los snapshots de reemplazo completo de go-like no deben enseñarse como streams de eventos idénticos.
  • @go-like/protoc-gen-like genera código Protobuf RPC con Context como primer argumento sobre Protobuf-ES. @go-like/transport-grpc-buf ofrece unary y server-streaming de Connect/gRPC-Web mediante Fetch; /native añade gRPC estándar con las cuatro cardinalidades, incluidas client-streaming y bidi. Es una vía independiente del camino interno Fetch/SSE.
  • Los defaults de providers de go-micro y go-kratos, los loops de retry, el half-close de streams y los defaults de selectors dependen de la versión. Usa la tabla de commits upstream fijados en el registro de investigación y vuelve a comprobarla antes de publicar una nueva comparación.

Qué elegir ​

Si tu problema principal es...Empieza con...Añade go-like cuando...
Controllers, modules, decorators y DINestJSNecesitas una frontera explícita alrededor de un recurso existente o una llamada interna y estás dispuesto a escribir el adaptador
Rutas HTTP Node, hooks y encapsulation de pluginsFastifyNecesitas composición de ciclo de vida más allá del host o contratos internos de servicios unary
Rutas Web Standards entre runtimesHonoNecesitas ciclo de vida de App/Server, llamadas internas o propiedad de providers
Composición de schemas y rutas centrada en BunElysiaNecesitas fronteras explícitas de ciclo de vida y transporte, conservando Elysia
Middleware Node mínimoKoa más un routerNecesitas el contrato de ciclo de vida o de llamadas internas que falta, no otro router
Procedures con tipos segurostRPCTambién necesitas discovery explícito de servicios, propiedad de providers o un ciclo de vida de Core
Stack de microservicios Gogo-micro o go-kratosEstás construyendo una composición TypeScript separada, no un port compatible a nivel de source
Piezas TypeScript para servicios entre runtimesgo-likeUsa solo los paquetes y providers que resuelven la frontera que necesitas

La respuesta correcta puede ser usar ambos sistemas. go-like es más útil cuando su modelo de propiedad explícita elimina una ambigüedad real; añadir todos los paquetes a una aplicación que ya funciona con otro framework contradice el objetivo de piezas pequeñas.

Anclas de evidencia ​

Las afirmaciones de go-like en esta página se pueden rastrear al árbol actual y a los entrypoints de los paquetes:

  • README.md para el alcance del producto y sus exclusiones explícitas;
  • packages/core/src/app.ts para App, Server, el arranque, stop y el comportamiento de timeout;
  • packages/web/src/context.ts para el Handler estándar y el bridge de Context;
  • packages/client/src/index.ts para las opciones de Client, pooling, retry y el pipeline de intentos;
  • packages/server/src/index.ts para handlers internos unary y dispatch de rutas;
  • packages/transport/src/types.ts y packages/transport/src/endpoint.ts para las fronteras Fetch Request/Response y defineService;
  • packages/registry/src/types.ts y packages/registry/src/selector.ts para snapshots, filters, selectors y feedback.

El registro de investigación también guarda estas entradas de comparación externas fijadas:

Las URLs son referencias de comparación, no una afirmación de que esta fase de documentación haya descargado o revalidado cada página upstream. Vuelve a comprobar releases tags o commits antes de cambiar una afirmación sensible a la versión.