<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="pl-pl">
<link rel="self" type="application/atom+xml" href="https://forum.atnel.pl/feed.php?f=61&amp;t=24869&amp;mode" />

<title>ATNEL tech-forum</title>
<link href="https://forum.atnel.pl/index.php" />
<updated>2025-11-08T18:45:34+01:00</updated>

<author><name><![CDATA[ATNEL tech-forum]]></name></author>
<id>https://forum.atnel.pl/feed.php?f=61&amp;t=24869&amp;mode</id>
<entry>
<author><name><![CDATA[SunRiver]]></name></author>
<updated>2025-11-08T18:45:34+01:00</updated>
<published>2025-11-08T18:45:34+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=24869&amp;p=239330#p239330</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=24869&amp;p=239330#p239330"/>
<title type="html"><![CDATA[Golang -- Moje droga ....]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=24869&amp;p=239330#p239330"><![CDATA[
Jakiś czas już programuje w Go, stworzyłem kilka projektów i kilka mniej lub bardziej użytecznych programików.<br />osobiście zdecydowanie jestem już poza etapem juniora , teraz zbliżam się do etapu senior, oczywiście żaden ze mnie guru <br />wciąż się uczę i choc swobodnie przenoszę na kod nie tylko swoje pomysły,  to wciąż wiele nauki przede mną. Niemniej jest to już <br />taki etap w którym mogę sobie pozwolić na pewne przemyślenia czyli jak zaczyna się każda<strong><em> gołowa</em></strong> przygoda ...<br /><br />Na początku jest cisza ............  wstawiłbym tu jakiś &quot;silence box&quot; w środku ciemnego lasu ......................<br />Mam oto nowy projekt, w nim pusty plik main.go i serce pełne entuzjazmu.<br />Ładuję przykładowy program &gt; słynne Hello World &lt;&lt; patrząc na magiczne napisy ....<br />Otwieram terminal, wpisuję magiczne go run . Czuję się jak czarodziej.... <br />I nagle otwiera się portal nowych możliwości i magii i właśnie odkryłem magiczną formułę -  fmt.Println().<br /><br />Potem przychodzi czas na napisanie czegokolwiek .....  <br /><br /><br /><strong>Etap 1: Odkrywca</strong><br /><br />„Wow! Goroutines! To jak wątek, tylko szybszy!”<br /><br /><br />[syntax=c]for i := 0; i &lt; 10; i++ {<br />go fmt.Println(&quot;Witaj z goroutine&quot;, i)<br />}[/syntax]<br /><br /><br /><strong>Komentarz:</strong>  Hura działa!<br />A potem.... nie działa.<br />A potem działa....  z kolejnością 9, 2, 5, 0, 7, 1… i nie wiem, dlaczego.<br />To Go uczy mnie pierwszej lekcji: „deterministyczność jest dla słabych.”<br /><br /><strong>Etap 2: Optymista</strong><br /><br />„Nie potrzebuję sync.WaitGroup, ja czuję, kiedy goroutine się skończy.”<br /><br /><br />[syntax=c]go doSomething()<br />fmt.Println(&quot;Gotowe!&quot;)[/syntax]<br /><br /><br /><strong>Komentarz:</strong> fiuuu  i w sumie gotowe… tylko doSomething() jeszcze trwa... trwa... trwa ....<br />to właśnie pierwszy kontakt z asynchronią.<br />i pierwsze zwątpienie w człowieczeństwo.<br /><br /><strong>Etap 3: Panikujący</strong><br /><br />„Nie wiem, czemu się zawiesiło, ale spróbuję to naprawić… close(ch)?”<br /><br /><br />[syntax=c]for v := range ch {<br />fmt.Println(v)<br />}<br />close(ch)[/syntax]<br /><br /><br /><strong>Komentarz: </strong>panic: close of closed channel ...... Co jest przecież dobrze napisałem ...<br />I tak poznaje drugą brutalną zasadę Go:<br />Kanały są jak związki — zamyka tylko ten, kto wysyła.<br /><br /><strong>Etap 4: Debugger z modlitwą</strong><br /><br />„Nie wiem, co się dzieje, więc dodałem fmt.Println(&quot;tu&quot;).”<br /><br /><br />[syntax=c]fmt.Println(&quot;1&quot;)<br />go doStuff()<br />fmt.Println(&quot;2&quot;)<br />fmt.Println(&quot;3&quot;)[/syntax]<br /><br /><strong>Komentarz: </strong>i nagle logi zaczynają żyć własnym życiem. Jakby coś opętało mój program ....<br />Widzisz „1”, potem „3”, potem panikę.<br />Moje fmt.Println stają się dla mnie religią.<br />To nic że logi przypominają hieroglify, ale przynajmniej coś się dzieje.<br /><br /><strong>Etap 5: Eksperymentator</strong><br /><br />„Słyszałem, że można użyć contextu. To pewnie coś fajnego.”<br /><br /><br />[syntax=c]ctx, cancel := context.WithCancel(context.Background())<br />go func() {<br />doSomething(ctx)<br />}()<br />defer cancel()[/syntax]<br /><br /><br /><strong>Komentarz:</strong> Wygląda profesjonalnie.<br />Nie mam absolutnie pojęcia, co to robi .....<br />Ale.... wygląda profesjonalnie.<br /><br /><strong>Etap 6: Tester przez przypadek</strong><br /><br />„Nie planowałem testów, ale go test i tak się odpaliło.”<br /><br /><br />[syntax=c]func TestMagic(t *testing.T) {<br />   if 2+2 != 5 {<br />       t.Fatal(&quot;czemu?&quot;)<br />   }<br />}[/syntax]<br /><br /><br /><strong>Komentarz: </strong> Pierwszy czerwony test.<br />Pierwsze t.Fatal().<br />Pierwsze przeczucie, że życie to pasmo niekończących się refaktorów.<br /><br /><strong>Etap 7: Pokora</strong><br /><br />„Nie wiem, czemu to działa. Ale działa.”<br /><br />[syntax=c]if err != nil {<br />  panic(err)<br />}[/syntax]<br /><br /><br /><strong>Komentarz:</strong>  to zdecydowanie najczęściej kopiowany fragment kodu w karierze każdego juniora.<br />Wiem już, że Go nie wybacza, ale nagradza za prostotę.<br />Zaczynam rozumieć: „im mniej magii, tym mniej bólu.”<br /><br /><strong>Podsumoiwanie etapu .... </strong><br /><br />W pewnym momencie, docieram wreszcie do etapu gdy  Go przestaje mnie zaskakiwać —<br />bo zaczyna mnie wychowywać. Z można powiedzieć uporem maniaka uczy cierpliwości, dyscypliny i tego, że:<br />- nil to nie wróg, tylko niezrozumiany przyjaciel,<br />- goroutine leak to po prostu sposób, w jaki runtime mówi „zrób przerwę”,<br />- a go vet to takie twoje lepsze ja, lub surowsze sumienie.<br />- i jeśli coś działa — nie pytaj dlaczego, tylko zrób commit.<br /><br />Dociera do mnie, że każdy senior kiedyś był juniorem.<br />Tylko...  niektórzy lepiej ukrywają swoje pierwsze panic(). <br />I wiem już, że powoli, powoli staję się seniorem,<br />Bo moje TODO brzmi już nie jak plan,<br />ale jak pożegnanie.<br /><br />Tymczasem znów minęło kilka miesięcy i kilkadziesiąt kodów i projektów za mną.  zaliczam kolejny etap .... <br />tu wydaje mi się, że moje przemyślenia mogą być już znacznie głębsze bardziej pewne siebie .... ale .... to tylko złudzenie, <br />to  etap przejściowy pomiędzy naiwnym entuzjazmem, a cynicznym spokojem.<br />To moment, gdy wiem już, że Go nie wybacza… ale,  nadal próbuję z nim dyskutować.  A co .... przecież jestem mądrzejszy ... prawda ?<br /><br /><strong>„jeszcze walczę, ale już wiem, z czym”</strong><br /><br />Mam już dawno za sobą pierwszego panika, kilka race condition i jeden tajemniczy deadlock, który....  „zniknął sam” --&gt; magia ? , a może ingerencja obcych ? <br />Znam context, sync, interface{} i wierzę szczerze, że umiem je kontrolować. Tymczasem to w brew temu co się wydaje, to najniebezpieczniejszy etap kariery w Go...<br />na etapie MID --- wszystko się nam tylko wydaje  .....<br /><br /><strong>Etap 1: Mam misję ...</strong><br /><br />„Napisałem własny framework, bo standardowa biblioteka jest zbyt prosta.”<br /><br /><br />[syntax=c]func HandleRequest(req *Request) Response {<br />mw := &#91;&#93;Middleware{Log, Auth, RateLimit, Recover}<br />return Chain(mw...)(req)<br />}[/syntax]<br /><br />Wygląda świetnie.<br />Działa… dopóki .... nie działa.<br />Zaczynam wierzyć, że prostota jest przereklamowana, że to taki chwyt marketingowy .....<br />Do czasu..... aż nil pointer przypomina mi brutalnie, skąd przyszedł.<br /><br /><strong>Etap 2: Władca Goroutines</strong><br /><br />„Używam errgroup — jestem profesjonalistą.”<br /><br /><br />[syntax=c]g, ctx := errgroup.WithContext(context.Background())<br /><br />for _, job := range jobs {<br />   job := job<br />   g.Go(func() error {<br />       return job.Run(ctx)<br />    })<br />}<br /><br />if err := g.Wait(); err != nil {<br />     log.Println(&quot;błąd grupy:&quot;, err)<br />}[/syntax]<br /><br />Mam pełną kontrolę nad współbieżnością. To cudowne uczucie ... jestem bogiem ...<br />Do momentu, gdy ktoś dorzucił go func() w środku job.Run()…<br />i nagle moja cudowna grupa robi się bardziej anarchiczna niż zorganizowana.<br />Koszmar z przed miesięcy powraca ....<br /><br /><strong>Etap 3: Ekspert od błędów</strong><br /><br />„Używam errors.Join, bo tak jest nowocześnie.”<br /><br /><br />[syntax=c]err := errors.Join(dbErr, cacheErr, apiErr)<br />if err != nil {<br />log.Println(&quot;kombinowany błąd:&quot;, err)<br />}[/syntax]<br /><br /><br />Teraz mam jeden błąd,   błąd który zawiera trzy błędy, które zawierają jeden główny błąd — brak sensu.<br />Ale... przynajmniej jest idiomatyczne... <br /><br /><strong>Etap 4: Refaktorysta</strong><br /><br />„Nie podoba mi się context.Context – napiszę własny.”<br /><br /><br />[syntax=c]type MyContext struct {<br />Done chan struct{}<br />Data map&#91;string&#93;any<br />}[/syntax]<br /><br /><br />Nie podobał mi się globalny context, więc stworzyłem potwora - taki lokalny problem globalny .<br />Mogę sobie pogratulować  – od teraz jestem oficjalnie Go-midem.  Mogę sobie przyznać order z ziemniaka...<br /><br /><strong>Etap 5: Tester z misją</strong><br /><br />„Pokrycie testami 90%! Tylko.... nikt nie wie, co testują.”<br /><br />[syntax=c]func TestSomething(t *testing.T) {<br />got := DoIt()<br />want := DoIt()<br />if got != want {<br />t.Errorf(&quot;expected %v, got %v&quot;, want, got)<br />}<br />}[/syntax]<br /><br /><br />Nie, nie to nie jest żaden test, to dialog między dwiema kopiami tej samej funkcji.<br />Ale w raporcie CI wygląda pięknie.<br /><br /><strong>Etap 6: Filozof runtime’u</strong><br /><br />„Nie wiem, kto odpala te goroutines, ale najwyraźniej są szczęśliwe.”<br /><br /><br />[syntax=c]for {<br />go doBackgroundTask()<br />time.Sleep(time.Second)<br />}[/syntax]<br /><br /><br />Mam goroutines, które żyją dłużej niż niektóre projekty, mówi się , że przetrwają ludzkość ....<br />Wiem, że to źle, ale… przecież runtime się nie skarży.<br /><br /><strong>Etap 7: Pragmatyczny zen</strong><br /><br />„To nie bug, to emergentne zachowanie systemu.”<br /><br /><br />[syntax=c]select {<br />case &lt;-ctx.Done():<br />return<br />default:<br />// żyj chwilą<br />}[/syntax]<br /><br /><br />Nie szukam już doskonałości, jestem nią .... <br />Teraz poszukuję równowagi.<br />Bo już wiem, że Go to nie język programowania – to styl życia.<br /><br /><strong>Podsumowanie tego etapu </strong><br /><br />Mid to stan przejściowy między „chcę wszystko przepisać”, a „niczego nie dotykam, bo działa.”  <br />To moment, w którym zaczynam wreszcie rozumieć, że idiomatyczne Go to nie reguły — to proces dojrzewania.<br /><br />Ale znów mija kilka miesięcy i klika projektów i programów mniej więcej znajduję się tu teraz. <br />Czyli w miejscu z którego wyraźnie widać jak z czasem zmienia się moje if err != nil<br /><br /><strong>Etap 1: Idealista</strong><br /><br />„Każdy błąd musi mieć sens.”<br /><br /><br />[syntax=c]if err != nil {<br />return fmt.Errorf(&quot;nie udało się wczytać pliku: %w&quot;, err)<br />}[/syntax]<br /><br /><br />Czysto, pięknie, zgodnie z konwencją.<br />Właściwie to jestem dumą dla każdej codereview.<br /><br /><strong>Etap 2: Pragmatyk</strong><br /><br />„Nie ma co przesadzać.”<br /><br />[syntax=c]if err != nil {<br />return err<br />}[/syntax]<br /><br />Minimalizm absolutny...<br />Mniej słów, więcej spokoju.<br />Wreszcie pojawia się zen.<br /><br /><strong>Etap 3: Realista</strong><br /><br />„Nie wiem, czemu znowu nie działa, ale lognę.”<br /><br /><br />[syntax=c]if err != nil {<br />log.Println(&quot;coś poszło nie tak:&quot;, err)<br />}[/syntax]<br /><br /><br />Nie naprawiam  – obserwuję.<br />To już nie jest zwykły błąd, to informacja zwrotna od wszechświata.<br /><br /><strong>Etap 4: Filozof</strong><br /><br />„Nie ma błędów, są tylko ścieżki alternatywne.”<br /><br />[syntax=c]_ = doSomething()[/syntax]<br /><br />Cisza....<br />Żadnych logów, żadnych błędów.....<br />Osiągnąłem nirwanę !!!<br /><br /><strong>Etap 5: Senior</strong><br /><br />„if err != nil { this is fine }”<br /><br />[syntax=c]if err != nil {<br />// TODO: naprawić kiedyś  (fajnie to wygląda w kodzie nie?  Gufim?) <br />}[/syntax]<br /><br />Znam wszystkie bugi, ale żyję z nimi w harmonii.,,<br />Wiem, że stabilność projektu to stan umysłu....<br /><br /><strong>Epilog Epilogu</strong><br /><br />Go nauczył mnie:<br />-- popełniać błędy idiomatycznie,<br />-- potrafię napisać od ręki taki race condition, którego nawet go vet się nie spodziewa,<br />-- zdaję sobie sprawę , że context to nie tylko „kontekst” — to stan emocjonalny programisty.<br />-- perfekcja jest przereklamowana,<br />-- umiem pisać funkcje bez argumentów, które ....  i tak zwracają błędy.<br />-- umiem perfekcyjnie użyć sync.WaitGroup, żeby poczekać...  poczekać na coś, co już się zawiesiło.<br />-- umiem zrobić slice, taki specjalny slice,  który dzieli pamięć z trzech innych slice’ów, a każdy z nich zmienia coś innego.<br />-- dokumentacja to też kod,<br />-- a panic() ?  to tylko manifest pasji. <br />-- i przede wszystkim: wiem, że := <strong>to broń masowego shadowingu.</strong><br /><br /><br />Pozostaje mi jeszcze jeden etap. Etap w którym zapewne odkryję wejście do Narni , albo Matrixa , ale na pewno się podzielę z wami<br />moimi przemyśleniami ...    w tej chwili na pewno możecie zapamiętać te kilka zasad , choć bardziej nazwałbym to:<br /><br />Objawione prawdy Go !!!!<br /><br />---&gt; <em>panic()</em> nie rozwiązuje problemów, ale przynajmniej robi je głośnymi.<br />---&gt; <em>context.WithTimeou</em>t zawsze wygasa wtedy, gdy właśnie zaczyna działać.<br />---&gt; <em>go fmt </em>nie naprawi Twojego życia, ale sprawi, że będzie wyglądało schludnie.<br />---&gt; <em>defer</em> jest jak obietnica — złożona przez kogoś, kto już dawno odszedł z projektu.<br />---&gt; <em>interface{}</em> to taki wieeeeeeeeellllllki worek — wszystko się zmieści, ale potem nikt nie wie, co tam jest i po co.<br />---&gt; <em>errgroup </em>to świetny sposób na współdzieloną katastrofę.<br />---&gt; <em>„idiomatyczne Go”</em> znaczy: „napisz tak, żeby nie dało się tego poprawić bez flame waru na GitHubie.”<br />Na koniec zostaje nam <em>nil...</em>,  a nil... nil zawsze czeka.  <br /><br />Na ciąg dalszy przyjdzie jeszcze poczekać… droga przede mną długa. Ale myślę, że to dobry moment na morał – nie tylko z tej opowieści, <br />ale z całego materiału w <a href="https://forum.lothar-team.pl//viewforum.php?f=134"  class="postlink">&gt;&gt;&gt; cookbooku &lt;&lt;&lt;</a>. Coś, do czego warto wracać. <br /><br />Nowy język kusi i ekscytuje, ale droga do mistrzostwa w Go bywa męcząca. Relacja z nim jest trudna, choć jego prostota bije po oczach niczym LED-y w starym gracie.<br /><br />Go nie jest sexy – ale jak każda zdrowa relacja, daje stabilność.<br />W Go nie chodzi o klasę, tylko o package main.<br />Nie chodzi w nim o dziedziczenie, tylko o kompozycję cierpliwości i logów.<br /><br />A jeśli kiedyś Twoje go build przejdzie za pierwszym razem…  --- sprawdź, czy na pewno jesteś w dobrym katalogu. <br /><br />Go to język dla tych, którzy chcą zbudować coś, co przetrwa. I w tym – w prostocie i cierpliwości – kryje się jego piękno.<br /><br />Zapamiętaj, młody padawanie Go:<br /><br />Kiedy patrzysz w goroutine,<br />goroutine patrzy w Ciebie.<br />Przyszłość widzi Twą – a jasna ona nie jest…<br />Nie wszystkie one znikną. Niektóre z nich są niemal nieśmiertelne.<br />Zostaną na długo po Tobie ..... <br /><br />,  a nil ??   .... wciąż czeka ...... <br /><br />Więcej .... znajdziecie <a href="https://forum.lothar-team.pl/viewforum.php?f=123"  class="postlink">&gt;&gt;&gt; tutaj &lt;&lt;&lt;</a>przyjaciele ...  zapraszam<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=58">SunRiver</a> — 8 lis 2025, o 18:45</p><hr />
]]></content>
</entry>
</feed>