Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Go-Swagger в продуктиве
Search
Ilya Kaznacheev
May 30, 2020
Programming
530
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Go-Swagger в продуктиве
Ilya Kaznacheev
May 30, 2020
More Decks by Ilya Kaznacheev
See All by Ilya Kaznacheev
Road to four nines
dreamworm
0
51
Many Layers of Availability
dreamworm
0
120
Stateful Solutions: A Hands-On Guide to FSM in Golang
dreamworm
0
230
CQRS
dreamworm
0
210
Building a Cloud-Native PaaS
dreamworm
0
180
Distributed System State Management: When Transactions Are Long and SLA Is High
dreamworm
0
180
How To Create Saga-Free Distributed Transactions
dreamworm
0
98
Architectural decisions in building distributed systems
dreamworm
0
54
Распределенные транзакции без саг
dreamworm
0
230
Other Decks in Programming
See All in Programming
Atomic Design, Enforced: Scaling Mobile Design Systems (next.app devCon / droidCon Berlin 2026)
steliosf
PRO
0
120
Starting & Sustaining Code-Based E2E Testing for Non-Coding QA Teams( #jasstniigata )
teyamagu
PRO
1
900
残高管理から台帳サービスへの進化
artoy
0
140
IBM Bob Dojo #1 仕様駆動開発入門
oniak3ibm
PRO
0
350
phperだってパンチカードでコーディングしたい
o0h
PRO
0
200
Ghostty + Neovimで作る 透明でカッコ良い開発環境
j341nono
0
150
When benchmarks go bad - what I learned from measuring performance wrong
hollycummins
0
130
20260914 AIエージェント時代のPlatform Engineering LLM基盤とプロダクトの責務境界線
kanfab1
7
2.4k
速く作れる。その次は、速く確かめられる開発へ 〜AIネイティブ開発を支える、Shift Down〜 / Can build fast. Next, moving to development where we can verify fast.
rkaga
8
5.5k
mrbgem 三角測量 開発
ogom
0
200
App Storeの外へ──日本のiOSサイドローディング入門 for iOSDC Japan 2026
yuukiw00w
0
310
パズルゲームの作り方 / how to make puzzle games
kaityo256
PRO
2
270
Featured
See All Featured
Fireside Chat
paigeccino
43
4k
Embracing the Ebb and Flow
colly
88
5.2k
Reflections from 52 weeks, 52 projects
jeffersonlam
356
21k
Building Adaptive Systems
keathley
44
3.2k
How to Align SEO within the Product Triangle To Get Buy-In & Support - #RIMC
aleyda
2
1.8k
Facilitating Awesome Meetings
lara
57
7.2k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
508
140k
Exploring the relationship between traditional SERPs and Gen AI search
raygrieselhuber
PRO
3
4.3k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
31
3.4k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
133
20k
Building a Modern Day E-commerce SEO Strategy
aleyda
45
9.2k
Optimizing for Happiness
mojombo
378
71k
Transcript
Go-Swagger в продуктиве взлеты и падения
Илья Казначеев Remote Backend SWE Основатель Golang Voronezh Ведущий подкаста
Z-Namespace Организатор конференций и митапов Любитель кофе
Golang Voronezh - ~30 активных участников - митапы - мероприятия
для новичков - открыто и дружелюбно t.me/golang_vrn meetup.com/Golang-Voronezh
что такое swagger?
None
SOAP JSON-PRC GraphQL gRPC OData REST
Representational state transfer (REST) is a software architectural style that
defines a set of constraints to be used for creating Web services Wikipedia
None
swagger: "2.0" info: title: Pet API version: "1.0.0" basePath: /api
schemes: - http paths: /pets: get: summary: List all pets parameters: - name: limit in: query description: "How many items to return at one time" required: true type: integer responses: 200: description: an paged array of pets 400: description: unexpected error
None
None
почему мы используем swagger?
команда синхронизирует изменения в API...
None
библиотеки go-swagger/go-swagger ✭ 5.2 K swaggo/swag ✭ 2.7 K deepmap/oapi-codegen
✭ 440 … grpc-ecosystem/grpc-gateway ✭ 8.5 K
go-swagger
генерация кода swagger generate server -t internal/api --exclude-main
структура сгенерированных файлов internal/api ├ models │ └ ... └
restapi ├ operations │ └ ... ├ configure_<your_service_name>.go ├ doc.go ├ embedded_spec.go └ server.go
как мы генерируем код rm -rf internal/api && mkdir -p
internal/api swagger generate server -t internal/api --exclude-main go mod tidy
? вроде все просто
НЕТ
есть некоторые проблемы - go-swagger - это фреймворк, а не
библиотека - куча сгенерированных типов на каждый чих - несовместим с популярными http библиотеками
давайте фиксить!
net/http хендлеры type CustomResponder func(http.ResponseWriter, runtime.Producer) func (c CustomResponder) WriteResponse(w
http.ResponseWriter, p runtime.Producer) { c(w, p) } func MetricsHandler(p instruments.GetMetricsParams) middleware.Responder { return CustomResponder(func(w http.ResponseWriter, _ runtime.Producer) { promhttp.Handler().ServeHTTP(w, p.HTTPRequest) }) }
простые middleware api := operations.NewSwaggerPetstoreAPI(swaggerSpec) api.InstrumentsGetMetricsHandler = instruments.GetMetricsHandlerFunc(MetricsHandler) api.AddMiddlewareFor("GET", "/metrics",
SomeMiddleware) srv := restapi.NewServer(api) srv.Serve()
middleware с кастомным хендлером h := api.Serve(nil) r := chi.NewRouter()
r.Use( middleware.Recoverer, ) r.With(AuthMiddleware).Group(func(r chi.Router) { r.Handle("/user/*", h) }) r.Mount("/", h) srv.ConfigureAPI() srv.SetHandler(r) srv.Serve()
настройки вне configure_<your_service_name>.go api.Logger = log.Printf api.HTMLProducer = runtime.TextProducer() srv
:= restapi.NewServer(api) srv.EnabledListeners = []string{"http"} srv.Port = conf.HTTPPort srv.Host = conf.HTTPAddr
кастомные имена методов /store/order/{orderId}/items: get: tags: - store summary: Find
purchase order items parameters: - name: orderId in: path required: true type: integer func GetOrderItems( param store.GetStoreOrderOrderIDItemsParams, ) middleware.Responder { items, err := getOrderItems(param.OrderID) if err != nil { return store.NewGetStoreOrderOrderIDItemsNotFound() } res := &models.OrderItems{} // // fill resopnse // return store.NewGetStoreOrderOrderIDItemsOK(). WithPayload(res) }
кастомные имена методов /store/order/{orderId}/items: get: tags: - store summary: Find
purchase order items operationId: getOrderItems parameters: - name: orderId in: path required: true type: integer func GetOrderItems( param store.GetOrderItemsParams, ) middleware.Responder { items, err := getOrderItems(param.OrderID) if err != nil { return store.NewGetOrderItemsNotFound() } res := &models.OrderItems{} // // fill resopnse // return store.NewGetOrderItemsOK(). WithPayload(res) }
встроенная валидация OrderItems: type: object properties: message: type: string maximum:
3 # swg/internal/api/models internal/api/models/order_items.go:45:55: cannot convert m.Message (type string) to type float64
шпаргалка по валидации numbers and integers - multipleOf - maximum
- minimum - exclusiveMaximum - exclusiveMinimum strings - maxLength - minLength - pattern arrays - maxItems - minItems - uniqueItems - maxContains - minContains objects - maxProperties - minProperties - required - dependentRequired any type - type - enum - const
расширения (костыли) x-omitempty x-nullable x-isnullable x-order x-go-custom-tag x-schemes x-go-name x-go-type
x-go-json-string x-go-enum-ci
юнит-тесты func GetOrderByID(param store.GetOrderByIDParams) middleware.Responder { order := models.Order{ ID:
123, PetID: 456, Quantity: 20, Status: "approved", } if param.OrderID != order.ID { return store.NewGetOrderByIDNotFound().WithPayload(&models.ErrorMessage{ Code: http.StatusNotFound, Message: http.StatusText(http.StatusNotFound), }) } return store.NewGetOrderByIDOK().WithPayload(&order) }
юнит-тесты tests := []struct { name string req store.GetOrderByIDParams code
int want string }{ { name: "good test", req: store.GetOrderByIDParams{OrderID: 123}, code: 200, want: `{"id":123,"petId":456,"quantity":20,"status":"approved"}`, }, { name: "bad test", req: store.GetOrderByIDParams{OrderID: 456}, code: 404, want: `{"message":"Not Found", "code":404}`, }, }
юнит-тесты for _, tt := range tests { t.Run(tt.name, func(t
*testing.T) { rr := httptest.NewRecorder() GetOrderByID(tt.req).WriteResponse(rr, runtime.JSONProducer()) assert.JSONEq(t, tt.want, rr.Body.String(), "wrong response body") assert.Equal(t, tt.code, rr.Code, "wrong response code") }) }
None
полезные ссылки json-schema.org/specification.html swagger.io/docs/specification/2-0 goswagger.io bit.ly/go-swagger-in-production
бонус A pluggable go-swagger (in development) github.com/ilyakaznacheev/go-plugger
бонус 2 Insomnia Designer insomnia.rest/products/designer
None
ilyakaznacheev