smithy-go is the Go code generator and runtime for Smithy. It has two major components:
- Codegen (
codegen/) — A Smithy build plugin written in Java that generates Go client/server/shape code from Smithy models. - Runtime (
./, top-level Go module) — The Go packages that generated code depends on at runtime.
The primary downstream consumer is aws-sdk-go-v2.
. # Root Go module (github.com/aws/smithy-go)
├── auth/ # Auth identity + scheme interfaces
│ └── bearer/ # Bearer token auth
├── aws-http-auth/ # Separate module: AWS SigV4/SigV4A HTTP signing
├── codegen/ # Java/Gradle: Smithy code generator
│ ├── smithy-go-codegen/ # Main codegen source (Java)
│ └── smithy-go-codegen-test/ # Codegen integration tests
├── container/ # Generic container types
├── context/ # Context helpers
├── document/ # Smithy document type abstraction
│ └── json/ # JSON document codec
├── encoding/ # Wire format encoders/decoders
│ ├── cbor/ # CBOR (used by rpcv2Cbor)
│ ├── httpbinding/ # HTTP binding serde helpers
│ ├── json/ # JSON encoder/decoder
│ └── xml/ # XML encoder/decoder
├── endpoints/ # Endpoint resolution types
├── internal/ # Internal utilities (singleflight, etc.)
├── io/ # I/O helpers
├── logging/ # Logging interfaces
├── metrics/ # Metrics interfaces
│ └── smithyotelmetrics/ # Separate module: OpenTelemetry metrics adapter
├── middleware/ # Middleware stack (the core of the operation pipeline)
├── ptr/ # Pointer-to/from-value helpers
├── testing/ # Test assertion helpers for generated protocol tests
│ └── xml/ # XML comparison utilities
├── time/ # Smithy timestamp format helpers
├── tracing/ # Tracing interfaces
│ └── smithyoteltracing/ # Separate module: OpenTelemetry tracing adapter
└── transport/
└── http/ # HTTP request/response types and middleware
# Run unit tests
make unit# Build and test codegen
cd codegen && ./gradlew build
# Publish to local Maven for downstream use
cd codegen && ./gradlew publishToMavenLocalThe codegen artifact version is fixed at 0.1.0 and is not published to
Maven Central — you MUST publishToMavenLocal.
The operation pipeline is built on a middleware stack defined in middleware/.
Steps execute in order: Initialize → Serialize → Build → Finalize →
Deserialize. Each step is a middleware.Step that holds an ordered list of
middleware. The codegen generates middleware registrations for each operation.
Each wire format has its own encoder/decoder under encoding/. These are
low-level — they produce/consume raw tokens or values, not full Smithy shapes.
Generated serde code calls into these packages.
GoWriter extends Smithy's SymbolWriter and is the primary mechanism for
generating Go source. It has two distinct writing styles that must not be
confused.
Inherited from SymbolWriter. Arguments are positional and referenced with
$-prefixed format characters. Each $X consumes the next argument in order.
Format characters:
$L— Literal (toString). Strings, names, anything that should be inserted verbatim.$S— String, quoted. Wraps the value in Go double-quotes.$T— Type (Symbol). Inserts the symbol name and auto-adds its import.$P— Pointable type (Symbol). Like$Tbut prepends*if the symbol is marked pointable.$W— Writable. Evaluates aWritable(lambda/closure) inline.$D— Dependency. Adds aGoDependencyimport, expands to empty string.
Numbered variants ($1L, $2T, etc.) allow reusing the same argument
multiple times. The number is 1-indexed and refers to the position in the
argument list:
// $1L is used twice, $2L once — only 2 args needed
writer.write("type $1L struct{}\nvar _ $2L = (*$1L)(nil)",
DEFAULT_NAME, INTERFACE_NAME);openBlock/closeBlock manage indentation for braced blocks. Arguments are
positional:
writer.openBlock("func (c $P) $T(ctx $T) ($P, error) {", "}",
serviceSymbol, operationSymbol, contextSymbol, outputSymbol,
() -> {
writer.write("return nil, nil");
});Uses $name:X syntax where name is a key in a Map<String, Object> and X
is the format character. Arguments are passed as one or more maps. This is the
preferred style for new code — it is more readable and less error-prone
than positional args.
return goTemplate("""
func $name:L(v $cborValue:T) ($type:T, error) {
return $coercer:T(v)
}
""",
Map.of(
"name", getDeserializerName(shape),
"cborValue", SmithyGoTypes.Encoding.Cbor.Value,
"type", symbolProvider.toSymbol(shape),
"coercer", coercer
));Rules:
goTemplate(String, Map...)is a static method that returns aWritable(aConsumer<GoWriter>lambda). It does NOT write immediately.writeGoTemplate(String, Map...)is an instance method that writes immediately to the writer.- Maps are merged into the writer's context scope for the duration of the template. Multiple maps can be passed and are applied in order.
- The writer pre-populates common symbols in context:
fmt.Sprintf,fmt.Errorf,errors.As,context.Context,time.Now.
ChainWritable— Collects multipleWritables and composes them with newlines between each. Use.compose()(with newlines) or.compose(false)(without).
For symbols, use SmithyGoDependency.*.valueSymbol("Name") or
SmithyGoDependency.*.pointableSymbol("Name").