There are existing tools for generating Golang clients based on OpenAPI specs but the generated code often isn't clean and easy to read. go-sdk-gen
aims to generated code that's closer to what one would write if writing the SDK manually. For example, splitting the generated code into individual files that themselves are well organized.
On the other end of the spectrum lay SDK generators like fern, stainless, or speakeasy. Those are capable of generating high-quality SDKs but have steep pricing and you are vendor-locking yourself in.
If you want to see how this looks, checkout the examples.
Install the latest version of go-sdk-gen
using
go install github.com/sumup/go-sdk-gen/cmd/go-sdk-gen@latest
And generate your SDK:
go-sdk-gen --mod github.com/me/mypackage --package mypackage --name 'My API' ./openapi.yaml
go-sdk-gen
generates structured SDK that is easy to navigate. Operations are grouped under tags and go-sdk-gen works under the assumption that each operation has one tag and one tag only.
When bootstrapping new project go-sdk-gen will generate all the necessary code for a valid SDK. On following runs it will update only code related to your OpenAPI specs but won't touch the client implementation and other files. This leaves you with the option to customize the client and add other features as necessary. You can opt out of this behavior using the --force
flag.
As a bade minimum, you will need to provide full path of your module (if you are bootstrapping new SDK), package name, and the source OpenAPI specs:
go-sdk-gen generate --mod github.com/me/mypackage --package mypackage --name 'My API' ./openapi.yaml
For further options see
go-sdk-gen help
If you find yourself in a need of customizing the generated code the easiest way to do so is by wrapping the go-sdk-gen
in your own script and hooking into the OpenAPI specs generation lifecycle.
package main
import (
"fmt"
"github.com/getkin/kin-openapi/openapi3"
"github.com/sumup/go-sdk-gen/pkg/builder"
)
func main() {
spec, err := openapi3.NewLoader().LoadFromFile(specs)
if err != nil {
return err
}
builder := builder.New(builder.Config{
Out: "./",
Pkg: "myapp",
// TODO: customization here
})
if err := builder.Load(spec); err != nil {
return fmt.Errorf("load spec: %w", err)
}
if err := builder.Build(); err != nil {
return fmt.Errorf("build sdk: %w", err)
}
}