Golang

W ramach podcastu “Porozmawiajmy o IT” miałem okazję porozmawiać z Bartłomiejem Klimczakiem o języku programowania Go.

Posłuchaj naszej rozmowy w wersji audio 🎧 👇

Cześć! Mój dzisiejszy gość z IT jest związany od 11 lat, pochodzi ze światka PHP-owego, parę lat temu zmienił stack na Go. Bloger, szkoleniowiec, spiker, organizuje lokalny Meetup o Go, jest Google Developer Expertem w kategorii Go. Prywatnie dumny mąż, ojciec uroczej córki. Moim i Waszym gościem jest Bartłomiej Klimczak.

Cześć, Bartku! Bardzo miło mi gościć Cię w podcaście.

Cześć! Dziękuję za zaproszenie.

Obserwując to, co wrzucasz na przykład na Twittera, to tam widzę, że bardzo często pojawiają się takie dwie literki: G i O, więc pomyślałem, że musimy o tym Go, o tym Golangu porozmawiać, bo obserwuję też, że zyskuje na popularności. Muszę przyznać, że jest to dla mnie obca technologia, więc z chęcią wyciągnę coś z Ciebie i się z nią zapoznam. Dzięki więc, że przyjąłeś zaproszenie i rozpoczynam, jak zawsze u mnie, od pytania, czy słuchasz podcastów. Jeśli tak, to może masz jakieś swoje ulubione audycje.

Tak, kiedyś dużo częściej słuchałem podcastów, teraz ze względu na to, że pracuję z domu, nie jeżdżę do pracy, to mam tego czasu na podcasty mniej, ale z tych, co słuchałem albo słucham do tej pory, to są Piątki Na Produkcji, bardzo fajny podcast, Porozmawiajmy o IT, może kojarzysz [śmiech].

Coś mi świta.

Na podsłuchu od Niebezpiecznika, Przeprogramowani — ostatnio to odkryłem i mają tam kilka fajnych odcinków, Better Software Design, Patoarchitekci i jeśli oni słuchają tego podcastu, to błagam, zacznijcie z powrotem nagrywać, bo to zarąbisty podcast. Znalazłem tylko jeden w miarę fajny związany z Golangiem, to jest Go Time. A jeśli już takie pozatechniczne, to jest Pan Tabletka dla rodziców — to jest bardzo fajny podcast, gdzie facet rozmawia o odporności ogólnie, nie tylko u dzieci oraz Pani Swojego Czasu od kuchni.

Pana Tabletki nie znałem, ale słyszałem, że faktycznie wiele osób już poleca, więc muszę sobie zerknąć, co tam Pan Tabletka nadaje. Dzięki za te polecenia. Dobra, Bartek, to powiedz mi, zanim zaczniemy sobie mówić o zapleczu Go, to powiedz, co Ciebie skłoniło do tego przeskoku z PHP do Go.

Odpowiedź jest dość prosta: trochę moja nieodpowiedzialność i troszeczkę na spontana, można tak to ująć. Wcześniej pracowałem właśnie dużo w PHP-ie i byłem w firmie, gdzie byłem zmęczony bardziej tym, w jaki sposób się wytwarza oprogramowanie tam i pomyślałem sobie, że jak już zmieniam pracę, to chcę trafić do fajnej pracy, niezależnie od technologii. Więc wylądowałem w firmie, która się nazywała Brainly, gdzie mają 95% back-endu napisane w Golangu. Ja, kiedy aplikowałem, powiedziałem, że jestem w środkach PHP, o Golangu wiem, że istnieje i że go stworzył Google, i czy to nie jest żaden problem. Powiedzieli, że: „Spoko, nauczymy Cię” i okazało się, że mnie przyjęli. I tak mniej więcej wyglądała moja zmiana z języka PHP na Golanga. Tam zacząłem pisać od razu aplikacje biznesowe i gdzieś po miesiącu, myślę że nawet zacząłem lubić ten język, bo pierwsze 3 tygodnie na pewno była taka walka ze starymi nawykami. Ale tak po miesiącu załapałem, o co w tym języku chodzi i już nawet przestałem z nim walczyć, a po paru miesiącach nawet go lubię.

Ciekawe, ciekawe. To jest właśnie coś takiego, że często nie doceniamy, jak takie z pozoru przypadki decydują później o naszym życiu. Coś się dzieje, co później wpływa na ileś tam lat naszej kariery zawodowej. I tak było w Twoim przypadku, ale wydaje mi się, że musiałeś tego Golanga naprawdę polubić, bo teraz sporo robisz w kierunku popularyzacji czy dzielenia się różnymi rzeczami, które znajdujesz na temat tej technologii. Musiał Ci przypaść faktycznie do gustu, więc może to jednak taki przypadek nie był.

Może nie był, ale nie miałem innego wyboru, jak go polubić, bo tam wszyscy pisali w Golangu, więc musiałem go polubić.

Jasne, okej. To zacznijmy może tak historycznie, gdybyś powiedział parę słów o tym, jak ten język powstał, jak wyglądała jego historia, kto i w jakim celu właściwie go stworzył.

Skracając długą historię, można powiedzieć, że było sobie w Google’u trzech gości, których nazwiska sobie zanotowałem: Robert Griesemer, Rob Pike oraz Ken Thompson, którzy byli już mocno zmęczeni tym, w jaki sposób piszą aplikacje dla Google’a, gdzie w większości skupiali się na C i C++ i bardzo im się nie podobało to, w jaki sposób ten język wpływa na produktywność programistów. Na przykład jednym z takich wyzwań, które mieli, to kompilacja C++ aplikacji przy jakichś większych projektach trwała godzinę, dwie albo nawet cały dzień, co się może wydawać dość dziwne, ale w tamtych czasach, te 15 lat temu, to chyba nie było jeszcze aż tak rzadkie.

Więc zaczęli się rozglądać po Internecie w poszukiwaniu jakiejś alternatywy i nie znaleźli nic, co by mogło spełniać ich wymagania, bo nie tylko czas kompilacji był problemem, ale też to, że język C czy C++ mają bardzo dużo naleciałości i są dość skomplikowane. Szukali czegoś prostego, szybkiego, gdzie ten developer experience będzie jak najlepszy. Nie udało im się na tamten moment znaleźć niczego ciekawego, więc zaczęli tworzyć specyfikację języka, który uważali, że miałby sens, co chyba im zajęło około roku. Gdzieś po roku przyszedł do nich, właśnie nie pamiętam, który dokładnie z tej trójki, powiedział: „Widziałem Waszą specyfikację i na kolanie w międzyczasie napisałem do niego kompilator, bo mi się spodobało” — i takie są początki Golanga.

Ciekawe. Co byś powiedział na temat zastosowań, gdzie on jest używany, bo ja muszę przyznać szczerze, że takie pierwsze skojarzenie, które mam, nawet niestety jedyne skojarzenie z tym językiem, to są zastosowania serwerowe, jako taki następca, lepsza wersja C, że gdzieś to siedzi na serwerze. Dlatego powiedz proszę, gdzie się ten język stosuje obecnie.

Można go zastosować wszędzie, nie ma ograniczeń, gdzie go nie można użyć, to jest język ogólnego zastosowania. Powstał z myślą o chmurze, dlatego te Twoje skojarzenia z tą chmurą, infrastrukturą. Korzysta się z niego w bardzo wielu obszarach, najwięcej w chmurze, później w narzędziach CLI, takich jak na przykład Docker, Terraform, potem — tu pewnie niektórych zaskoczę — to są aplikacje biznesowe. Widziałem też, że można w Golangu pisać, kompilować go do WebAssembly, więc można tworzyć aplikacje webowe, można pisać aplikacje desktopowe, takie zwykłe. Są też bidingi do biblioteki Qt, więc mamy też cały ten toolchain dostępny, pisząc w Golangu. Jest też projekt, który się nazywa TinyGo, który jest taki bardzo okrojoną wersją Golanga, która się skupia na urządzeniach wbudowanych, więc można sobie [11:19 ns] też programować w Golangu.

Myślę, że o plusach tego języka jeszcze za chwilę będziemy rozmawiać, ale czymś, co się na pewno przebija, jest wydajność i to przemawia do rozumu. Natomiast ja osobiście znam takie zastosowania języka Go, gdzie on jest jakimś elementem szerszego stacku i najczęściej jest wykorzystywany tam właśnie, gdzie ta wydajność, ta konkurencyjność jest potrzebna, tam się go zaprzęga do pracy. Czy Ty myślisz, że Go jest albo będzie rozpatrywany jako język klasy enterprise, czyli w bankach, różnych firmach ubezpieczeniowych, w dużych instytucjach? Czy to się już dzieje albo jest szansa, że faktycznie będzie tam adaptowany?

Chcąc nie chcąc, Golang tam już prawdopodobnie działa, bo pewnie działają na Kubernetesie albo korzystają z Dockera. A jeśli chodzi o to, czy aplikacje na przykład biznesowe w banku czy aplikacje finansowe, to tak, wiem że na przykład w Alior Bank na pewno piszą w Golangu, w innych bankach wydaje mi się, że też. Wiem, że Golang nie jest bardzo popularny, ale mimo wszystko tam właśnie, gdzie ta wydajność jest ważna, a na przykład nie ma nikogo, kto by zjadł zęby na optymalizacji w JVM-ie, to łatwiej jest przerzucić się na Golanga i skorzystać z jego dobrodziejstw niż wgryzać się w te niuanse JVM-a czy .Neta.

Czyli jeśli chodzi o wybór czegoś od początku, to być może to jest właśnie lepsza technologia, jeśli mamy możliwość wyboru. Język sam w sobie jeszcze nic nie zdziała, to jest ważne, żeby on był oparty na dobrych praktykach, żeby dawał też ten developer experience na odpowiednim poziomie, ale to jest jedna rzecz. O sukcesie całej technologii świadczy jeszcze ten tooling wokoło. I dlatego chcę Cię teraz zapytać o te narzędzia, biblioteki, frameworki, IDE — wszystko to, co jest potrzebne deweloperowi na co dzień, żeby w tym stacku Go stworzyć jakieś produkcyjne aplikacje.

Żeby stworzyć jakąś produkcyjną aplikację, to tak naprawdę potrzebujemy binarki z Go oraz jakikolwiek edytor tekstu. I mamy wszystkie podstawowe narzędzia, które nam pozwolą pisać w Golangu, bo w tej bibliotece, w tej binarce Go, mamy cały kompilator, linker, mamy też toole na przykład do uruchamiania testów, do profilowania aplikacji i tym podobne, więc w standardzie dostajemy dość sporo. Jeśli chodzi o biblioteki, to od pewnego czasu można powiedzieć, że jest wysyp. Zdarzają się średniej jakości te biblioteki, ale ogólnie z racji tego, że ten język jest dość prosty i ciężko jest w niektórych momentach zepsuć to, co można by było zepsuć w innych językach, to jakość w porównaniu z innymi ekosystemami jest spoko. Rewelki nie ma, ale jest spoko.

Jeśli chodzi o to, jakie to są biblioteki, to jeśli się pisze rzeczy bardziej DevOpsowe, to się powinno znaleźć prawie wszystko, bo to jest taki konik tego języka. Więc jeśli się pisze jakieś CLI albo rzeczy, które działają po stronie infrastruktury, to bardzo dużo rzeczy już tam jest napisanych. Jeśli chodzi o rzeczy takie typowo webowe, to są biblioteki, ale nie myślcie o tym, że znajdziecie tutaj jakiegoś przeportowanego Spring Boota albo Symfony z PHP-a — czegoś takiego nie ma. I to nie ze względu na to, że się nie pisze webowych aplikacji, wręcz przeciwnie, ale ze względu na to, że po pierwsze biblioteka standardowa już i tak sporo nam daje, a dwa, że w tym języku jest troszeczkę inna filozofia i nie ma takiej dużej potrzeby na to, żeby te rozbudowane frameworki istniały.

Rozumiem. A czy jest coś, co przypomina menedżer pakietów albo jakieś miejsce w sieci, gdzie na przykład takie biblioteki są zbierane, skąd możemy sobie je pobrać? Działa coś takiego?

Tak, menedżer pakietów został chyba ze dwa, trzy lata temu wbudowany w Golanga. Wcześniej nie było, to był jeden z argumentów przeciwko Golangowi. Od jakiegoś czasu mamy Go modules, które pomagają właśnie w zarządzaniu tymi pakietami. Jest strona, która się nazywa go.dev, gdzie możemy sobie wyszukać wszystkie te biblioteki, które są na GitHubie, GitLabie.

Czy jakieś IDE przychodzi Ci do głowy, czy to raczej de facto dowolny edytor z pluginem do kolorowania składni wystarcza?

Jeśli jesteś minimalistą, to tak, ale są też IDE typowo skupiające się na Golangu. Jednym z nich jest Goland od IntelliJ-a, według mnie bardzo mocno konkuruje z VS Codem — to są chyba dwa najbardziej popularne. Ja na przykład bardzo często korzystam z Vima, ma swoje niuanse, ale też się sprawdza. Więc: Goland, VS Code oraz Vim czy Emacs albo z czegokolwiek korzystacie.

Czyli każdy znajdzie coś dla siebie, coś odpowiedniego. Powiedziałeś tutaj o tym, że być może te problemy czy niedociągnięcia na przykład z dużych projektów pisanych w C czy w C++ niejako zmotywowały twórców, żeby pomyśleć o specyfikacji nowego języka. Chcę Cię teraz zapytać o to, czy jest coś takiego unikalnego w Go, coś, czym mocno różni się od innych języków lub coś, w czym bardzo przypomina inne języki. Chodzi mi o to, żeby na krajobrazie tych różnych języków osadzić Go, czy to jest coś bardzo unikalnego, czy mimo wszystko czerpie z jakichś wcześniejszych technologii.

Z tego, co wiem, to twórcy Golanga nie wymyślili niczego nowego. Jeśli chodzi o filozofie, które są w tym języku, nie ma tam niczego, co nie było wymyślone w latach 70., 80. Wydaje mi się, że taką największą unikalnością tego języka jest filozofia. Ta filozofia skupia się przede wszystkim na tym, żeby ten język był prosty. Kiedy mówię „prosty”, mam na myśli prosty do czytania, do zrozumienia oraz żeby ten język był na tyle prosty, żeby developer experience było jak najlepsze. W tym głównie chodzi o to, że kiedy czytamy, kiedy mamy jakiś kod, to przeważnie raz, dwa, może trzy razy go napiszemy, ale przy okazji ze dwieście, trzysta, czterysta razy go przeczytamy.

Więc w Golangu bardzo się skupia na tym, żeby się go jak najlepiej czytało, co też ma swoje konsekwencje w tym, że wielu rzeczy w tym języku nie ma. I to jest jeden z takich argumentów przeciwko Golangowy, czy argument w rękach hejterów Golanga, że bardzo wielu rzeczy w tym języku nie ma. I w tym języku tych rzeczy nie ma, ze względu na to, że starają się trzymać ten język jak najprostszy. Dodanie każdego nowego ficzera wiąże się z tym, że automatyczny język staje się bardziej skomplikowany, potrzeba troszeczkę więcej czasu, żeby się nauczyć nowej składni, mechanik, które tam działają pod spodem i tym podobne. Więc żeby ograniczyć ten próg wejścia, autorzy starają stworzyć go jak najprostszym.

Myślę też, że utrzymanie później takiego języka, który ma mnóstwo ficzerów jest po prostu trudniejsze, trzeba myśleć o tej kompatybilności wstecznej i tak dalej. Z tego co ja obserwuję, rozwój języka, który co chwilę dostaje nowe ficzery, w pewnym momencie zwalnia bardzo, bo ten bagaż, który trzeba ciągnąć ze sobą, jest straszny.

Pamiętam, jeden z moich znajomych opowiadał historię. On pisze bardzo dużo w JVM-ie, w Javie i miał taki przypadek, że został poproszony o pomoc w znalezieniu jakiegoś buga, z którym sobie deweloperzy nie mogli poradzić. Spędził nad tym sporo godzin i okazało się, że jeden z deweloperów, który oczywiście już nie pracował wtedy w tej firmie, w Javie napisał sobie swoją własną implementację jednej z anotacji, której nazwa wygląda prawie że identycznie jak ta, która działa w bibliotece standardowej. I jak czytali ten kod, to nie zauważyli tej różnicy, a tam był jakiś błąd, co spowodowało, że bardzo dużo czasu spędzili na szukaniu błędu. Na przykład w Golangu takiej rzeczy nie znajdziesz, w sensie w tym języku jest bardzo mało magii. Mam na myśli, że jest bardzo mało rzeczy, kiedy jak patrzysz na kod, to się pod spodem może wydarzyć coś więcej niż widzisz. Na przykład nie ma tych anotacji, tak jak jest w JVM-ie.

Myślę, że dla większych projektów to ma wtedy bardzo duże znaczenie, że im więcej tej magii, teoretycznie wydaje się, że to zwiększa produktywność, przyspiesza development, ale później niestety, jak już wchodzimy w taką fazę utrzymania, to przysparza sporo problemów.

Tak, ale to też ma pewne swoje konsekwencje i to jest jeden z głównych argumentów przeciwko Golangowi, że kiedy piszesz kod, to masz bardzo dużo „if error jest różne od nila, to wtedy zwróć error” i tym podobne. I to potrafisz mieć w jednej funkcji, w zależności od tego, ile masz takich operacji, nawet sporo, ale dzięki temu widzisz, gdzie coś może pójść nie tak. W Golangu nie rzuca się wyjątków, tam się zwraca błędy, jak normalne wartości w zmiennych, więc jeśli jakaś funkcja może pójść nie tak, to nie jest tak, że ona rzuci sobie wyjątek i zostanie złapany gdzieś dalej. Ona w sposób explicit pokaże Ci, że ta funkcja może później tak i musisz w jakiś sposób to obsłużyć, czy zignorować ten błąd, czy go zalogować, czy przesłać do dalej.

Okej, to skoro już o tym rozmawiamy, to powiedz proszę, jakie są największe braki czy problemy, z którymi obecnie Golang musi się mierzyć. Co osobiście Ty w nim lubisz, a czego Ci tam brakuje?

Jeśli chodzi o narzekanie na Golanga, to myślę, że mógłbym równie długo narzekać, co i go chwalić. Jeśli chodzi o to, czego w tym języku nie lubię, to myślę, że biblioteka standardowa jest według mnie trochę za mała, tam jest zbyt mało rzeczy, z których normalnie programiści korzystają, a to według mnie tam powinno być, choćby na przykład obsługa [23:34 ?], gdzie żeby sprasować [23:38 ?], to musimy zaciągać jakieś inne zależności, a to jest tak popularny problem, że według mnie to powinno być w standardowej bibliotece. I też w standardowej bibliotece są pakiety, które nie są, delikatnie mówiąc, dopieszczone. Jest na przykład pakiet Go plugin, który od jakiegoś czasu już nie jest wspierany i nie ma w ogóle implementacji go na Windowsa, więc na Windowsie z tego ficzera nie skorzystasz, mimo że to jest w bibliotece standardowej. Jeśli chodzi o to, czego mi w tym języku brakuje, to chyba z takich wodotrysków brakuje mi enumów, które by działały na podobnej zasadzie, jak to jest w Ruście. Nie licząc tego, to myślę, że ja bym do tego języka nie dodawał specjalnie więcej rzeczy właśnie ze względu na to, żeby go zaskomplikować zbyt dużo.

Jak Ciebie słucham, to wydaje mi się, że to chyba język dla minimalistów może być. [śmiech]

Można tak powiedzieć. Jeśli chodzi o plusy tego języka, bo wydaje mi się, że bardziej na niego póki co narzekałem, aniżeli go chwaliłem. Według mnie wielkim plusem jest to, że on jest dość prosty, w sensie on jest prosty i szybki. Szybkość możemy zrozumieć dwojako: czas wykonywania Twojego kodu jest dość szybki oraz to, że na przykład kompilacja jest też bardzo szybka. Właśnie ze względu na to, że język jest prosty, to można go szybko sprasować, szybko skompilować i nie ma tam żadnych niepotrzebnych kroków pomiędzy, które by mogły wydłużać czas kompilacji. Kolejnym plusem według mnie jest to, w jaki sposób działają interfejsy i one bardzo podobnie działają, jak w TypeScripcie, gdzie w przeciwieństwie na przykład do Javy, kiedy się definiuje klasę, to musisz napisać, które interfejsy ona implementuje.

Tutaj działa to trochę na odwrót, że tworzysz sobie strukturę, bo klas nie mamy, tworzysz sobie strukturę z jakimiś metodami i w miejscu, gdzie chcesz z tej struktury korzystać, to albo możesz powiedzieć, że chcesz dokładnie tę strukturę, albo sobie zdefiniujesz mały interfejs, który ta struktura będzie implementować i po prostu w swoim kodzie wrzucasz tę swoją strukturę, która implementuje ten interfejs. I to jest dla mnie bardzo duży plus ze względu na to, że w tych językach Java, C Sharp, PHP i całej reszcie, musiałeś zawczasu stworzyć te interfejsy i bardzo często te interfejsy właśnie ze względu na to, że one były zawczasu i musiały spełniać więcej roli, to albo musiałeś stworzyć ich dużo, albo jeden trochę większy. W Golangu ten problem został tak rozwiązany, że możesz sobie jako klient jakiegoś API stworzyć interfejs, który po pierwsze będzie dużo łatwiej zamokować, bo będzie miał mniej metod, a dwa, że się możesz łatwo wyabstrahować i wyciągnąć z tych struktur, z tych funkcji tylko to, czego potrzebujesz tak naprawdę.

Kolejnym dużym plusem, z którego Golang słynie, to są Go rutyny. Mówi się o Go rutynach, że to są takie małe wątki. Trochę to prawda, trochę nieprawda. Ogólnie chodzi w tym o to, że nie mówimy z poziomu tego języka, że chcemy, żeby na przykład ta operacja wykonała się w oddzielnym wątku, tylko po prostu tworzymy sobie Go rutynę, która wykonuje jakiś kod, na zasadzie: „wykonaj mi ten kod kiedyś, wtedy, kiedy znajdziesz czas na jakimś procesorze, który akurat będzie wolny” i ja po prostu jestem zainteresowany tylko wynikiem i czekam na wynik. Prostota tego języka polega na tym, że właśnie my w ogóle nie zajmujemy się tak niskopoziomowymi rzeczami, jak tworzenie wątków, zamykanie wątków i tym podobne. Tym wszystkim zajmuje się Runtime, jesteśmy zwolnieni z tego. My tylko informujemy, że chcemy, żeby ta operacja się wykonała i że czekamy na informację zwrotną, kiedy to się skończy.

I dzięki temu, że to działa w taki sposób, ten schedule może stosować różnego rodzaju triki, polegające na tym, że na przykład ma dostępny tylko jeden wątek, więc żeby ten nasz kod się w miarę szybko wykonywał, to ma na przykład dziesięć Go rutyn odpalonych, to na tym jednym wątku po kolei, powoli wykonuje sobie każdą z tych Go rutyn, dzięki czemu mamy takie wrażenie, że to się wykonuje równocześnie. A kiedy tych wątków bardzo często jest więcej, to wtedy on potrafi sobie przerzucać między wątkami w dość sprytny sposób, żeby na przykład Go rutyna nie skakała zbyt często między wątkami i my się całkowicie tym nie przejmujemy, jesteśmy z tego zwolnieni, tylko informujemy o tym, że chcemy coś odpalić i jesteśmy zainteresowani wynikiem tego. Ty to wykonaj za mnie — na takiej zasadzie. Można powiedzieć, że fire and forget.

Jeśli chodzi o inne fajne ficzery, to to, że w Golangu też mamy GC i to był też jeden z argumentów, dlaczego twórcy Golanga nie chcieli pracować w C++, bo tam właśnie jest ręczne zarządzanie pamięcią. Więc chcieli mieć GC, ale które też nie będzie zbyt skomplikowane, które będzie szybkie, i też zastosowali pewne jakieś filozofie oraz podejścia do tego, żeby tak było. To też potrafi bardzo mocno zwolnić dewelopera z myślenia o tym, w jaki sposób zarządzać pamięcią. I to jest właśnie ukłon w stronę developer experience.

Kolejną fajną rzeczą, trochę wspomniałem o tym wcześniej, jest to, że funkcje potrafią zwrócić więcej niż jedną wartość. I to bardzo często się wykorzystuje w sytuacji, kiedy jakaś operacja może pójść nie tak. Tak jak wcześniej wspomniałem, na przykład powiedzmy, że chcemy stuknąć do jakiegoś zewnętrznego API i dostajemy albo zwrotkę z odpowiedzią od serwera, albo dostajemy błąd, musimy sobie zrobić tego „if-else’a” i sprawdzić, czy dostaliśmy błąd. Jeśli nie ma błędu, to wtedy możemy założyć, że ta zmienna zawiera te dane, których potrzebujemy.

👉 Czytaj dalej na: https://porozmawiajmyoit.pl/poit-144-golang/

kkempin’s dev blog

Dev and life blog.

kkempin’s dev blog

Dev and life blog. Thoughts about programming, design patterns, Ruby and life.

Krzysztof Kempiński

Written by

IT expert. Ruby on Rails/iOS/Elixir programmer. Blogger. Podcaster.

kkempin’s dev blog

Dev and life blog. Thoughts about programming, design patterns, Ruby and life.