---
id: e10df2108115b462a5ac2a289080a901
author: iwanhae
title: Go és az OpenAPI ökoszisztéma
description: Bemutatjuk azokat a könyvtárakat és stratégiákat, amelyek OpenAPI alapú API-fejlesztés során használhatók Go nyelven.
language: hu
date: 2024-10-18T06:07:43.092628696Z
path: /blog/posts/go-and-the-openapi-ecosystem-zd5a8e472
category: api
---

### Bevezetés

Amikor Go nyelven production backend szervert fejlesztünk, szinte minden fejlesztő számára az egyik első nehézség a következő kérdés:

> API dokumentálás, hogyan csináljam...?

Ha egy kicsit utánanézünk, hamar rájövünk, hogy az OpenAPI specifikációnak megfelelő dokumentáció készítése előnyös, és természetesen olyan könyvtárakat keresünk, amelyek integrálhatók az OpenAPI-val. Miután azonban ez a döntés megszületett, következik a második probléma:

> Rengeteg OpenAPI-kapcsolatos könyvtár van.. Melyiket használjam...?

Ez a dokumentum kezdő Go fejlesztők számára készült, akik ebben a helyzetben vannak, és egy rövid könyvtárismertetőt nyújt. A 2024 végi állapot alapján készült, és mivel a nyelvi ökoszisztéma folyamatosan változik, javasoljuk, hogy a dokumentumot használva mindig nézzék meg a legfrissebb híreket is.

### Az OpenAPI-hoz való megközelítések a könyvtárakban

Valószínűleg már ismert, hogy az OpenAPI a REST API-k egyértelmű definiálására és dokumentálására szolgáló specifikáció. Az API végpontjait, kéréseit és válaszformátumait YAML vagy JSON formátumban határozza meg, ami nemcsak a fejlesztőknek segít, hanem a frontend és backend kód generálásának automatizálásával csökkenti a felesleges ismétléseket és a kisebb emberi hibákat is.

Az OpenAPI projektbe való természetes integrálása érdekében a Go ökoszisztéma könyvtárai nagyjából három stratégiát követnek.

#### 1. Go kommentek összeállítása OpenAPI specifikációs dokumentummá

Az OpenAPI szerint fejlesztett API-k egyik nehézsége, hogy a tényleges dokumentáció és a megvalósító kód külön fájlokban, egymástól távol helyezkedik el, ezért gyakran előfordul, hogy a kódot frissítik, de a dokumentációt nem, vagy fordítva.

Egy egyszerű példa:

1. Módosítjuk az API logikáját a `./internal/server/user.go` fájlban,
2. miközben a tényleges dokumentáció a `./openapi3.yaml` fájlban található, így könnyen elfelejthetjük ennek módosítását.
3. Ha nem vesszük észre a problémát, és így nyitunk Pull Requestet, a kollégák felülvizsgálata során
4. a reviewerek sem látják a `./openapi3.yaml` változásait, ezért előfordulhat, hogy az API specifikáció változatlan marad, miközben a tényleges API implementáció megváltozik, ami komoly problémát okozhat.

Ha az API dokumentációt Go kommentek formájában írjuk meg, ez a probléma bizonyos mértékig orvosolható. Mivel a kód és a dokumentáció egy helyen található, a kód módosításakor a kommenteket is egyszerűen frissíthetjük. A kommentek alapján automatikusan OpenAPI specifikációs dokumentumot generáló eszközök is léteznek.

Egy reprezentatív projekt a [Swag](https://github.com/swaggo/swag). A Swag a Go kód kommentjeit feldolgozva OpenAPI 2 formátumú dokumentumot generál. A használata egyszerű: a handler függvény fölé a adott könyvtár által meghatározott formátumban kell kommenteket írni.

```go
// @Summary 유저 생성
// @Description 새로운 유저를 생성합니다.
// @Tags Users
// @Accept json
// @Produce json
// @Param user body models.User true "유저 정보"
// @Success 200 {object} models.User
// @Failure 400 {object} models.ErrorResponse
// @Router /users [post]
func CreateUser(c *gin.Context) {
    // ...
}
```

Ha ilyen kommenteket írunk, a Swag nevű CLI feldolgozza ezeket, és OpenAPI 2 dokumentumot készít. Ez a művelet általában a CI folyamatban történik, a generált OpenAPI specifikáció pedig Git repositoryba, a végső build eredményekbe vagy egy külön, külső API-dokumentum-kezelő rendszerbe kerül, és más projektekkel való együttműködés során használják.

**Előnyök:**

- Mivel a kommentek a kóddal együtt találhatók, **a tényleges kód és a dokumentáció eltérésének valószínűsége csökken.**
- Külön eszköz vagy bonyolult konfiguráció nélkül, csupán kommentekkel **egyszerűen és szabadon dokumentálhatunk**.
- Mivel a kommentek nem befolyásolják a tényleges API logikát, **jól alkalmazhatók olyan ideiglenes funkciók hozzáadására, amelyeket nem akarunk nyilvánosan dokumentálni**.

**Hátrányok:**

- A kommentek számának növekedésével **a egyetlen kódfájl olvashatósága romolhat**.
- **Kommentek formájában nehéz lehet kifejezni** az összes API specifikációt.
- A dokumentum nem kényszeríti ki a kódot, ezért **nem garantálható, hogy az OpenAPI dokumentum és a tényleges logika megegyezik**.

## 2. Go kód generálása OpenAPI specifikációs dokumentumból

Van olyan megközelítés is, amely a Single Source of Truth (SSOT) forrását nem a Go kódban, hanem a dokumentumban helyezi el. Ez azt jelenti, hogy először az OpenAPI specifikációt definiáljuk, majd ez alapján generálunk Go kódot. Mivel az API specifikáció generálja a kódot, fejlesztési kultúrát tekintve kikényszeríthetjük, hogy először az API tervezés történjen meg, és mivel a specifikáció definiálása a fejlesztés legelején történik, a hiányosságokat korán észrevehetjük, így megelőzhető, hogy a fejlesztés befejezése után, az API specifikáció módosításával együtt az egész kódot át kelljen írni.

Ezt a megközelítést alkalmazó reprezentatív projekt az [oapi-codegen](https://github.com/oapi-codegen/oapi-codegen) és az [OpenAPI Generator](https://github.com/OpenAPITools/openapi-generator/tree/master/samples/server/petstore/go-echo-server). A használat egyszerű:

1. Írjunk YAML vagy JSON dokumentumot az OpenAPI specifikációnak megfelelően,
2. futtassuk a CLI-t,
3. és létrejön a megfelelő Go stub kód.
4. Ezután már csak az egyes API-k részletes logikáját kell megvalósítanunk, hogy a stub használható legyen.

Az alábbiakban egy példa látható az oapi-codegen által generált kódra:

```go
// StrictServerInterface represents all server handlers.
type StrictServerInterface interface {
	// ...
	// Returns all pets
	// (GET /pets)
	FindPets(ctx context.Context, request FindPetsRequestObject) (FindPetsResponseObject, error)
	// ...
}
```

Az oapi-codegen által az interfész alapján generált kód elvégzi a query paraméterek, a header és a body feldolgozását, a validációt, majd meghívja az interfészben deklarált megfelelő metódust. A felhasználónak csak ezt az interfészt kell implementálnia, és ezzel az API megvalósításhoz szükséges munka elkészül.

**Előnyök:**

- Mivel **a specifikáció készül el először, és utána kezdődik a fejlesztés**, több csapat párhuzamos munkavégzése esetén **a feladatok párhuzamosan haladhatnak**.
- A korábban ismétlődő, unalmas munkát igénylő kódrészek **automatikusan generálódnak**, így **a munkahatékonyság nő**, miközben **a hibakeresés továbbra is könnyű marad**.
- **Könnyen biztosítható, hogy a dokumentum és a kód mindig megegyezzen**.

**Hátrányok:**

- Az OpenAPI specifikáció alapos ismerete nélkül **kezdetben meredek lehet a tanulási görbe**.
- Mivel az API-t kezelő kód szerkezetét a projekt automatikusan generálja, **egyedi testreszabás esetén nehézkes lehet az alkalmazkodás**.

> A szerző megjegyzése.
> 2024 októberi állapot szerint az OpenAPI Generator által generált Go kód nemcsak az API logikát, hanem a teljes projektstruktúrát is kikényszeríti, és a merev szerkezet miatt nem alkalmas arra, hogy a production környezethez szükséges sokféle funkciót hozzáadjunk. Azoknak, akik ezt a megközelítést választják, erősen javasolt az oapi-codegen használata. A szerző az oapi-codegen + echo + StrictServerInterface kombinációt használja.

## 3. OpenAPI specifikációs dokumentum generálása Go kódból

Amikor tucatnyi vagy akár több száz ember fejleszt ugyanazon a szerveren, elkerülhetetlen probléma, hogy az egyes API-k közötti egységesség megbomolhat. Egy szemléletes példa: ha több mint 100 API endpoint specifikációját egyetlen OpenAPI YAML fájlban deklaráljuk, a fájl könnyen tízezer soron felüli szörnyeteggé válik, és új endpoint deklarálásakor elkerülhetetlenül ugyanazt a modellt többször definiáljuk, bizonyos mezőket kihagyunk, vagy a konvencióknak nem megfelelő path elnevezések születnek, így az egész API egységessége megbomlik.

Ennek megoldására külön OpenAPI YAML-tulajdonost is kijelölhetünk, vagy Linter-t fejleszthetünk, amely a CI folyamat során automatikusan felismeri a problémákat. Go nyelven azonban Domain-specific language (DSL) is definiálható, amellyel kikényszeríthető, hogy minden API egységes legyen.

Ezt a technikát alkalmazó reprezentatív projekt a Kubernetes, amely saját magán építi ki a rendszert külön könyvtár nélkül. Használhatjuk emellett a [go-restful](https://github.com/emicklei/go-restful) és a [goa](https://goa.design/) projekteket is. Az alábbiakban a `goa` használatának példája látható:

```go
var _ = Service("user", func() {
    Method("create", func() {
        Payload(UserPayload)
        Result(User)
        HTTP(func() {
            POST("/users")
            Response(StatusOK)
        })
    })
})
```

Ha ehhez hasonlóan fordítható Go kódot írunk, a `POST /users` API megvalósítása és dokumentációjának definiálása egyszerre készül el, ami nagy erősség.

**Előnyök:**

- Mivel minden a kódból származik, **könnyű az API egységességét fenntartani az egész projektben**.
- A Go erős típusrendszerét kihasználva **pontosabb és vitathatatlanabb specifikációt** kaphatunk, mint az OpenAPI3 összes funkciójának használatakor.

**Hátrányok:**

- **Az egyes keretrendszerek által definiált DSL-t meg kell tanulni**, és **nehéz lehet meglévő kódra alkalmazni**.
- Mivel a keretrendszer által javasolt szabályokat kötelezően követni kell, **a szabadság és a rugalmasság csökkenhet**.

**Összegzés**

Minden megközelítésnek vannak előnyei és hátrányai, ezért fontos, hogy a projekt követelményei és a csapat preferenciái alapján válasszuk ki a megfelelő módszert. A legfontosabb nem az, hogy melyik módszer a jobb általában, hanem az, hogy értékelni tudjuk, melyik megoldás a legmegfelelőbb a jelenlegi helyzetünkben, és magas fejlesztési produktivitással elérjük a **korai feierabendet** és a **kiegyensúlyozott munka-magánélet egyensúlyt**.

Bár a cikket 2024 októberi állapot szerint írtuk, a Go és az OpenAPI ökoszisztéma folyamatosan fejlődik, ezért kérjük, hogy a cikk olvasásának idejét is figyelembe véve kövessék nyomon a könyvtárak és projektek legfrissebb híreit, valamint azok megváltozott előnyeit és hátrányait.

Boldog Go életet kívánok~ 😘
