Several tools can be used to create SDKs from an OpenAPI spec. Let's use the oapi-codegen Go code generator to create a Go SDK, and then build a client using that SDK.
First, let's create a command to grab the OpenAPI spec so the service doesn't need to be running and you can generate the SDK as needed (e.g. as part of the API service release process).
packagemainimport("context""fmt""net/http""github.com/danielgtaylor/huma/v2""github.com/danielgtaylor/huma/v2/adapters/humachi""github.com/danielgtaylor/huma/v2/humacli""github.com/go-chi/chi/v5"_"github.com/danielgtaylor/huma/v2/formats/cbor")// Options for the CLI.typeOptionsstruct{Portint`help:"Port to listen on" short:"p" default:"8888"`}// GreetingOutput represents the greeting operation response.typeGreetingOutputstruct{Bodystruct{Messagestring`json:"message" example:"Hello, world!" doc:"Greeting message"`}}// ReviewInput represents the review operation request.typeReviewInputstruct{Bodystruct{Authorstring`json:"author" maxLength:"10" doc:"Author of the review"`Ratingint`json:"rating" minimum:"1" maximum:"5" doc:"Rating from 1 to 5"`Messagestring`json:"message,omitempty" maxLength:"100" doc:"Review message"`}}funcaddRoutes(apihuma.API){// Register GET /greeting/{name}huma.Register(api,huma.Operation{OperationID:"get-greeting",Method:http.MethodGet,Path:"/greeting/{name}",Summary:"Get a greeting",Description:"Get a greeting for a person by name.",Tags:[]string{"Greetings"},},func(ctxcontext.Context,input*struct{Namestring`path:"name" maxLength:"30" example:"world" doc:"Name to greet"`})(*GreetingOutput,error){resp:=&GreetingOutput{}resp.Body.Message=fmt.Sprintf("Hello, %s!",input.Name)returnresp,nil})// Register POST /reviewshuma.Register(api,huma.Operation{OperationID:"post-review",Method:http.MethodPost,Path:"/reviews",Summary:"Post a review",Tags:[]string{"Reviews"},DefaultStatus:http.StatusCreated,},func(ctxcontext.Context,i*ReviewInput)(*struct{},error){// TODO: save review in data store.returnnil,nil})}funcmain(){varapihuma.API// Create a CLI app which takes a port option.cli:=humacli.New(func(hookshumacli.Hooks,options*Options){// Create a new router & APIrouter:=chi.NewMux()api=humachi.New(router,huma.DefaultConfig("My API","1.0.0"))addRoutes(api)// Tell the CLI how to start your server.hooks.OnStart(func(){fmt.Printf("Starting server on port %d...\n",options.Port)http.ListenAndServe(fmt.Sprintf(":%d",options.Port),router)})})// Add a command to print the OpenAPI spec.cli.Root().AddCommand(&cobra.Command{Use:"openapi",Short:"Print the OpenAPI spec",Run:func(cmd*cobra.Command,args[]string){// Use downgrade to return OpenAPI 3.0.3 YAML since oapi-codegen doesn't// support OpenAPI 3.1 fully yet. Use `.YAML()` instead for 3.1.b,_:=api.OpenAPI().DowngradeYAML()fmt.Println(string(b))},})// Run the CLI. When passed no commands, it starts the server.cli.Run()}
Next, we can use the SDK by writing a small client script.
client/client.go
packagemainimport("context""fmt""github.com/my-user/my-api/sdk")funcmain(){ctx:=context.Background()// Initialize an SDK client.client,_:=sdk.NewClientWithResponses("http://localhost:8888")// Make the greeting request.greeting,err:=client.GetGreetingWithResponse(ctx,"world")iferr!=nil{panic(err)}ifgreeting.StatusCode()>200{panic(greeting.ApplicationproblemJSONDefault)}// Everything was successful, so print the message.fmt.Println(greeting.JSON200.Message)}