jgo

module
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 14, 2026 License: Apache-2.0

README

JGO

English | 简体中文

JGO is a standalone Go service framework and project scaffolding tool for HTTP/JSON and gRPC/protobuf services.

Runtime support, project scaffolding, contract generation, unified debugging, and developer workflow commands are available. Start with the documentation index or the quick-start guide.

Module

github.com/eyesofblue/jgo

The current release is v0.3.0; see CHANGELOG.md.

Prerequisites

Project type Required software
web Go 1.24.0 or later
grpc Go 1.24.0 or later, Buf 1.46.0, protoc-gen-go 1.36.7, protoc-gen-go-grpc 1.5.1
mixed The same Go and protobuf toolchain as grpc
proto The same Go and protobuf toolchain as grpc; no JGO runtime dependency

JGO has no required database, Redis, message queue, service registry, configuration center, or other private infrastructure. Private infrastructure can be integrated later through application components and HTTP/gRPC middleware.

Make sure the Go binary directory is in PATH:

export PATH="$(go env GOPATH)/bin:$PATH"

Install

Install a published version:

go install github.com/eyesofblue/jgo/cmd/jgo@v0.3.0
jgo --version

Use @latest when you intentionally want the newest published release.

For JGO framework development, you can also clone the repository and build from source:

go build -trimpath -o bin/jgo ./cmd/jgo
./bin/jgo --version

For gRPC, mixed, and proto projects, install the locked generators once per Go development environment:

jgo tools install
jgo tools check

JGO uses GOTOOLCHAIN=local and never downloads or switches Go toolchains silently. Exact module and tool versions are documented in docs/dependencies.md.

New project: create a service and its first API

Generated service projects default to github.com/eyesofblue/jgo v0.3.0; proto projects have no JGO runtime dependency. All project types default to the active go env GOVERSION; use --go-version to override it. Project creation runs go mod tidy and writes go.sum; offline environments can use --skip-tidy. During local framework development, add --jgo-replace /absolute/path/to/jgo; do not commit a machine-specific replacement for normal users.

Web service

Create the project, define the request/response models, add the API, and then generate code:

jgo new user-web \
  --module example.com/user-web \
  --type web
cd user-web

# Define the UpdateUserRequest and UserInfo Go structs under api/http/model/.
jgo api add UpdateUser \
  --method POST \
  --path /update_user \
  --request-params UpdateUserRequest \
  --response-data UserInfo

jgo api generate
# Implement the newly generated business method under internal/service/.
go test ./...
jgo run

A new Web project includes /hello and health checks, but api/http/openapi.yaml initially has no business operations. Normally, run jgo api add before generation instead of running jgo generate immediately after jgo new. Web services listen on :8080 by default.

HTTP responses use the stable {"code":0,"msg":"","data":...} envelope:

{"code": 0, "msg": "", "data": {"uid": 12345, "name": "Albert"}}

Business success is code: 0; HTTP status represents the transport result, while the integer code represents the business result.

gRPC service

jgo tools install installs the locked Buf and protobuf generators into the current Go development environment. Run it once per environment, not once per project:

jgo new user-rpc \
  --module example.com/user-rpc \
  --type grpc
cd user-rpc

jgo tools install # Run the first time this environment uses JGO gRPC.
jgo doctor
jgo rpc pbapi add GetUser --service UserRpcService
# Edit GetUserRequest; GetUserResponse already has code/msg, so add business fields from number 3.
jgo rpc generate
# Implement the generated UserRpcServiceGetUser method under internal/service/.
go test ./...
jgo run

The initial protobuf service name is derived from the project name; for example, user-rpc becomes UserRpcService with a sample Echo RPC. Keep or remove the sample when establishing the real contract. The gRPC Health service is always registered, and its address is read from configs/local.yaml.

JGO locks Buf 1.46.0, protoc-gen-go 1.36.7, and protoc-gen-go-grpc 1.5.1. gRPC business methods use <Service><RPC> names, such as UserRpcServiceGetUser; public protobuf service and RPC names remain unchanged.

Every JGO RPC response uses non-optional int32 code = 1 and string msg = 2; business success is 0. User-defined business fields start at number 3 and use optional only when they need to distinguish absence from an explicit zero value. jgo call grpc displays zero values such as 0, "", and false for ordinary fields while still omitting unset optional/message fields.

jgo doctor and generation commands enforce this convention for local and cross-file RPC responses and fail when the standard code/msg fields are missing.

When a business method explicitly returns jgo/errors.Error, the generated gRPC transport builds a Response containing its code/msg and keeps the gRPC status OK. Unknown errors, panics, cancellation, and timeouts that cannot produce a valid business Response use a non-OK gRPC status. Business codes are not duplicated in gRPC status details.

Shared protobuf module

Use a proto project when multiple services and callers must share one versioned contract module. The project name is arbitrary; company-api is only an example:

jgo new company-api \
  --module example.com/company-api \
  --type proto
cd company-api

jgo tools install # Skip when already installed in this Go environment.
jgo rpc pbapi add GetUser --service CompanyApiService
# Add another protobuf Service later when the module covers a new domain:
jgo rpc pbservice add OrderService
# Complete request and response fields in api/proto/company_api/v1/service.proto.
jgo rpc generate
jgo list
go test ./...

A proto project initially retains the generated CompanyApiService.Echo example. Use rpc pbservice add to add more Services to the same repository; do not run jgo new again. It has no cmd/server, configuration, business layer, or JGO runtime dependency. Generation only updates the public Go packages under gen/pb. Commit both .proto and gen/pb, tag the protocol module, then import packages such as example.com/company-api/gen/pb/company_api/v1 from server and caller projects. jgo run and the server-oriented jgo build intentionally reject proto projects.

Connect a published Service to a gRPC or mixed server:

jgo rpc server add UserService \
  --module example.com/company-api@v0.1.1
# JGO discovers the unique package, adds the module dependency, generates the
# server adapter and missing business methods, and runs go mod tidy.

Connect a typed client to any web, gRPC, or mixed service:

jgo rpc client add UserService \
  --module example.com/company-api@v0.1.1 \
  --name user \
  --address 127.0.0.1:9090

The generated business service receives the protobuf interface directly as s.RPC.User. client add writes rpc_client.user to configs/local.yaml and wires it through client/grpcx. The client --name is a stable code identifier and cannot be renamed after creation; choose another name by adding a separate client. Runtime values such as address, timeout, and TLS settings remain editable in YAML. Module release versions such as v0.1.1 do not select protobuf API v1/v2: JGO searches all generated packages for the Service. If the same Service exists in multiple packages, specify the exact import with --package.

Mixed service

A mixed project maintains both OpenAPI and protobuf contracts while sharing one business layer and application lifecycle:

jgo new user-service \
  --module example.com/user-service \
  --type mixed
cd user-service

jgo tools install # Skip if the locked tools are already installed in this environment.
jgo doctor
# Add the required APIs and complete their structs/proto messages as shown above.
jgo generate     # Generate both HTTP and gRPC code.
go test ./...
jgo run

Mixed projects listen on HTTP :8080 and gRPC :9090 by default; YAML, environment variables, or command-line flags can override both addresses.

Tracing and structured logging

Generated projects enable OpenTelemetry Trace Context by default. HTTP and gRPC propagate the standard W3C traceparent. OTLP export is disabled by default, so no Collector, Jaeger, or Tempo deployment is required. HTTP responses also expose X-Trace-ID for operational troubleshooting.

telemetry:
  tracing:
    enabled: true
    sample_ratio: 0.1
    exporter:
      enabled: false
      endpoint: "127.0.0.1:4317"
      insecure: true

When export is enabled, spans are sent over OTLP/gRPC. With export disabled, trace IDs are still created and propagated, but spans are neither recorded nor sent. Shutdown flushes and closes the tracer provider after the HTTP/gRPC servers stop.

Use the structured logx API for business logs:

logx.InfoCtx(ctx, "get user completed", "uid", uid)
logx.ErrorCtx(ctx, "get user failed", "uid", uid, "err", err)

DebugCtx, InfoCtx, WarnCtx, and ErrorCtx automatically add trace_id and span_id from the context. Printf-style InfoCtxf/ErrorCtxf APIs are intentionally not provided.

gRPC business errors still use response.code/msg with an OK gRPC status. Generated transports attach jgo.business_code and jgo.business_message to the active span so observability backends can distinguish business failures.

Outbound gRPC clients

client/grpcx owns named, reusable gRPC connections as an application component. Connections are lazy: an unavailable remote service does not block process startup, and the actual call returns gRPC Unavailable. Outbound dependencies do not change /healthz, which only reports the health of the current process.

Configure dependencies under rpc_client:

rpc_client:
  user:
    address: "dns:///user-rpc:9090"
    timeout: 3s
    tls:
      enabled: false
      server_name: ""
      ca_file: ""

The generated rpc client add wiring uses this runtime automatically. For manual integration, create the manager, obtain a connection, construct the generated protobuf client, and add the manager to the application before serving requests:

clients, err := clientgrpcx.New(map[string]clientgrpcx.Config{
    "user": {
        Address: configuration.RPCClient["user"].Address,
        Timeout: configuration.RPCClient["user"].Timeout.Duration,
    },
})
if err != nil {
    return err
}
connection, err := clients.Conn("user")
if err != nil {
    return err
}
userClient := userv1.NewUserServiceClient(connection)
application.Add(clients)

The default unary timeout is 3 seconds. A named client can override it; when the call context already has a deadline, the earlier of that deadline and the client timeout wins. TLS can use system roots or an additional CA file. JGO disables configured gRPC retries and does not retry business calls automatically. OpenTelemetry trace context is propagated, and transport failures are logged through the context-aware structured logger.

Existing service: add an API

Add an HTTP API
# 1. Add or reuse request and response Go structs under api/http/model/.
# 2. Add the operation to the OpenAPI contract.
jgo api add GetUser \
  --method GET \
  --path /get_user \
  --request uid:int64:required:query \
  --response-data UserInfo

# 3. Regenerate only the HTTP code.
jgo api generate
# 4. Implement the new business method; existing methods are preserved.
go test ./...
Add a gRPC API

For example, add GetUser to an existing UserService that already has other RPCs:

jgo doctor       # Verify the locked tool versions in the current environment.
jgo rpc pbapi add GetUser --service UserService
# Edit the request; the response already has code=1/msg=2, so add business fields from number 3.
jgo rpc generate
# Implement the generated UserServiceGetUser method.
go test ./...

If the same service name occurs in multiple proto files, select one with --file api/proto/.../service.proto. jgo rpc generate regenerates protobuf and transport code but never overwrites existing business methods.

Choose a generation command according to the changed contracts:

Command Scope
jgo api generate HTTP/OpenAPI code only
jgo rpc generate gRPC/protobuf code only
jgo generate All HTTP and gRPC code in the project; useful for mixed projects and CI

Debug APIs

Use the same JSON input for both protocols. JGO reads OpenAPI or protobuf descriptors and does not generate one-off debug programs:

jgo list
jgo call http GetUser --addr http://127.0.0.1:8080 --data '{"uid":12345}'
jgo call grpc UserRpcService.Echo --addr 127.0.0.1:9090 --data '{"message":"hello"}'

Both call commands support repeatable --header 'Name: Value' metadata and --timeout. gRPC prefers server Reflection and automatically falls back to protobuf files under api/proto/.

A generated project's README documents the stable workflow instead of duplicating an API inventory that can become stale. OpenAPI/proto files are the contract source of truth; use jgo list to inspect current HTTP and gRPC interfaces.

Developer workflow

jgo doctor
jgo generate
jgo list
jgo run
jgo build

Generate Bash or Zsh completion with jgo completion bash and jgo completion zsh. The versioning and release checklist is documented in docs/releasing.md.

jgo --version

Development verification

Run the complete local quality gate from the repository root:

make tools
make ci

This runs formatting checks, unit tests, race tests, go vet, CLI build, and real checks for web, gRPC, mixed, and proto projects. The generation check also starts an independently generated proto module, gRPC server, and Web caller to verify end-to-end trace propagation, the 3-second client timeout, Unavailable behavior, and process-only /healthz semantics.

Documentation

License

Apache License 2.0.

Directories

Path Synopsis
Package app manages the lifecycle of the components that make up a process.
Package app manages the lifecycle of the components that make up a process.
client
grpcx
Package grpcx manages reusable outbound gRPC client connections.
Package grpcx manages reusable outbound gRPC client connections.
cmd
jgo command
Package errors defines errors that can be transported safely across service boundaries without exposing their internal causes.
Package errors defines errors that can be transported safely across service boundaries without exposing their internal causes.
Package health provides HTTP liveness and readiness probes.
Package health provides HTTP liveness and readiness probes.
internal
call
Package call implements contract-driven HTTP and gRPC debugging calls.
Package call implements contract-driven HTTP and gRPC debugging calls.
command
Package command implements the JGO command-line interface.
Package command implements the JGO command-line interface.
generator/protobuf
Package protobuf safely updates protobuf contracts and generates gRPC code.
Package protobuf safely updates protobuf contracts and generates gRPC code.
generator/rpcbinding
Package rpcbinding connects shared generated protobuf modules to JGO services.
Package rpcbinding connects shared generated protobuf modules to JGO services.
template
Package templatefs exposes the project templates embedded in the JGO binary.
Package templatefs exposes the project templates embedded in the JGO binary.
Package logx provides structured, context-aware logging backed by slog.
Package logx provides structured, context-aware logging backed by slog.
Package middleware contains composable net/http middleware primitives.
Package middleware contains composable net/http middleware primitives.
accesslog
Package accesslog records one structured log entry for each HTTP request.
Package accesslog records one structured log entry for each HTTP request.
recovery
Package recovery converts handler panics into safe JSON errors.
Package recovery converts handler panics into safe JSON errors.
timeout
Package timeout limits HTTP handler execution and returns a standard JSON timeout response.
Package timeout limits HTTP handler execution and returns a standard JSON timeout response.
traceid
Package traceid exposes trace and span identifiers stored in OpenTelemetry contexts and adds the current trace ID to HTTP responses.
Package traceid exposes trace and span identifiers stored in OpenTelemetry contexts and adds the current trace ID to HTTP responses.
Package response writes the standard JGO HTTP/JSON response envelope.
Package response writes the standard JGO HTTP/JSON response envelope.
server
grpcx
Package grpcx provides a gRPC server component for app.App.
Package grpcx provides a gRPC server component for app.App.
httpx
Package httpx provides a safe net/http server component for app.App.
Package httpx provides a safe net/http server component for app.App.
Package telemetry configures OpenTelemetry for JGO applications.
Package telemetry configures OpenTelemetry for JGO applications.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL