Kitekintés a Go programozási nyelvre

Az év során alkalmam nyílt részt venni egy képzésen, ami bevezetőt nyújtott a Go programozási nyelv alapjaiba. Az ilyen kurzusok ugyan hasznosak, de ha csak ismerkedni szeretnénk, akkor a legjobb ötlet a hivatalos Tour of Go online anyagon végigmenni.

A következő szint, hogy ha valamit össze is akarunk rakni az új eszközünkkel, akkor neki kell látni valaminek, amiben ki lehet próbálni a helloworld példáknál nehezebbet és egyben a toolingot is.

Erre a célra egy bértömeg számoló alkalmazást választottam. Arra képes, hogy a dolgozói hierarchiában megmondja, hogy adott menedzser alatti dolgozóknak mennyi az összes bérköltsége.

Wagesum application

Amint látható, egy egyszerű CRUD alkalmazás, ami REST interface keresztül szolgálja ki a kéréseket, adatbázisban tárol adatokat és goroutinokkal segít javítani a sok lekérésből adódó terhelést.

Wagesum a github-on

Szubjektív szempontokat fogalmazok meg, és a változtatás joga is megillet. :) Állítólag a nyelv ötlete is akkor fogant meg az alkotók fejében, amikor a Google-nál éppen kávéztak egy hosszabb C++ buildre várva.

Kezdeti élmények, vélemény

Nekem olyan élmény, mintha a C nyelvet Python tulajdonságokkal, fél szemmel folyamatosan a Java-ra és Spring-re tekintve készítették volna, figyelembe véve és lehetőség szerint kerülve a C++ problémáit. A világon nagyon sok C és C++ fejlesztő van, akiknek a nyelv kényelmes lehetőséget kínál a microservice világba való átlépésre.

Vannak pointerek és van nil is, viszont nincs pointer aritmetika és nincs operator overloading sem. Nem hullatok könnyeket értük. Van Garbage collection, de alapból belefordul a binárisba, nem külső JVM mechanizmusok vezérlik.

Statikus linkelést használ. Ennek eredményeként képes sok mindent egyszerűsíteni, illetve ennek is köszönhető a rendkívül gyors fordítás, valamint az elérhető egy (!) futtatható állomány, ami mindent tartalmaz. Van ennek olyan hatása is, hogy a függőségek kezelésénél képes kiszűrni a nem használt library-kat, egy sima go mod tidy parancs helyrerázza a felduzzadt go.mod leírót.

A kód egységes kinézetéért beépített formázó és elemző áll rendelkezésre. Azaz könnyen és fájdalommentesen lehet egységes kód képet elérni mindenkinél. A hibakezelés kicsit furcsa a modern nyelvek kivétel kezeléséhez képest, de meg lehet szokni.

A Go nyelv nem objektum orientált nyelv, de struct segítségvel elérhető hasonló működés, leginkább a Pythonra hasonlít, ahogy func (s MyStruct) f(p param) (RetVal, error){…} ránézésre is mutatja a rokonságot.

A funkcionális paradigmát viszont messzemenően támogatja. Nagyon könnyű és kézenfekvő a kód közben is function-t definiálni. A wagesum alkalmazásban a emp_sal_service_test él is vele, de egyáltalán nem használja ki a teljes potenciálját.

Mindeközben a C őst nem is akarja letagadni, az interoperábilitás biztosított. Ebben a cikkben élő példát mutatnak be. Van azért hátulütője is, az SQLite támogatásnál például rögtön gcc után vágyakozott, így végül ki is vettem, pedig jó lenne egy pehelysúlyú, in-memory adatbázis a teszteknél.

A Convention over Configuration elvet talán kicsit túltolták. Az még tök jó, hogy a private és public kiírása helyett a láthatóságot a kis és nagybetűs kezdés jelzi. De amikor comment-be lehet írni test assertet, akkor azért felszalad a szemöldök. Oda azért nem kéne üzleti logikát írni.

Openapi és kód generálás

A kedvenc openapi generálók mind ismerik a Go nyelvet. Így most is elég volt egy tisztességes API leírást megalkotni.

docker run --rm -v ${PWD}:/local openapitools/openapi-generator-cli generate -i /local/api/wagesum-openapi.yaml  -g go-server  -o /local/internal/pkg --additional-properties=noservice,enumClassPrefix=true,featureCORS=false,onlyInterfaces,outputAsLibrary=true,sourceFolder=openapi

Így teljesíthetjük az API first class citizen elképzelést, és még kódot se kell írni. Viszont a generátor nem a legfrissebb, ötleteket azért így is ad, de a linter persze már tiltakozik.

A wagesum alkalmazásban az internal/pkg/openapi alatt találhatóak a generált források, de a service-eket átmozgattam másik package-be. Ez azért volt hasznos, hogy elkerülhessem a körkörös hivatkozást.

Eszközök

Egy programozási nyelvnél manapság kevésbé számítanak a tulajdonságai, ha nincs hozzá megfelelő eszközkészlet. A Go itt nagyon szépen teljesít, alapértelmezetten is rengeteg kényelmes eszközt kínál.

A legtöbb eszköz nyílt forráskódú, barátságos licenszeléssel. Ha Java világból érkezünk, akkor a Hibernate helyett ott a gorm. REST hívásokra van gorilla mux, létezik az echo, de alapszinten meg is lehet írni a beépített eszközökkel.

Project felépítésének kialakítására ezt a layout formát találtam, de sokan használják a /src könyvtárat a forráskódoknak. Mint látható, próbáltam tartani a szabványt.

A Vipert a túl sok függősége miatt dobtam, mert nem volt szükségem a lehetőségeinek többségére. Helyette az env minimalista környezeti változókra építő megoldását használtam.

Létezik egy rakat féle tesztelő framework, de nem annyira triviális velük dolgozni, mint mondjuk a JUnit/Mockito párossal. De a tesztelés már egyből támogatott és azonnal rendelkezésre áll, bármilyen függőség nélkül. Tehát fapadosan azonnal lehet akár TDD-vel indulni, még akkor is, ha később mást is hozzá szeretnénk adni.

Go rutinok és alkalmazásuk

A Go rutinok az egyik legelegánsabb és legérdekesebb megoldása a nyelvnek. Ezek lényegében pehelysúlyú szálak, amik az operációs rendszer szálaitól függetlenül üzemelnek.

No persze, nem az első, lehet itt Erlang-ot is emlegetni, de a Scala-nak a Zio framework szintén kínálja ezt, csak ők fiber néven nevezik. A Java-ba a Project Loom fogja elhozni nemsokára.

A wagesum alkalmazásban a lényeges rész az emp_sal_service goroutinjai teszik ki. Az ötlet annyi csak, hogy a hosszan futó, rekurzív lekérdezéseket párhuzamosítsuk, és channel-eken keresztül dolgozzuk fel.

Összefoglaló

A Go nyelv egy jól összerakott, jól támogatott programozási nyelv, kitűnő eszközkészlettel. Alacsony memória és processzor használat, hatékony megoldások jellemzőek rá. Számos területen viszont évtizedes tapasztalatokat hagy figyelmen kívül.

A Java világából érkezve nem érzem azt a késztetést, hogy azonnal áttérjek rá. Ott is vannak előremutató kezdeményezések, Scala, Kotlin és mások. Nyilván sokkal gyorsabban produktív tudok lenni.

Azonban megvan a helye a nyelvnek a palettán, a Kubernetes világában széles körben használják, így sikerre van ítélve. Mindenképpen megéri kipróbálni és kicsit beleszokni.

Linkek