abclinuxu.cz AbcLinuxu.cz itbiz.cz ITBiz.cz HDmag.cz HDmag.cz abcprace.cz AbcPráce.cz
AbcLinuxu hledá autory!
Inzerujte na AbcPráce.cz od 950 Kč
Rozšířené hledání
×
včera 10:35 | Komunita
V Portlandu probíhá pětidenní konference OSCON 2014 (O'Reilly Open Source Convention). Po dvou dnech tutoriálů dnes začínají přednášky. Úvodní přednášky (keynotes) je možné sledovat online. Videozáznamy všech tutoriálů a přednášek (program) budou k dispozici po skončení konference.
Ladislav Hagara | Komentářů: 1
21.7. 20:23 | Upozornění
Poslední upgrade Debianu Testing/Jessie přináší systemd jako náhradu za sysvinit. Ačkoli byl funkční systemd součástí Debianu Jessie již delší dobu, nebyl používán pro spouštění systému. Toho bylo možné docílit parametrem jádra při spuštění systému, kdy nebyl původní sysvinit nijak dotčen, nebo instalací balíku systemd-sysv, který původní init nahrazuje symlinkem na systemd. Tento balík je nicméně součástí posledního upgradu … více »
Migilenik | Komentářů: 78
21.7. 17:28 | Bezpečnostní upozornění
Vyšla verze 2.4.10 webového serveru Apache. Nejnovější verze řeší především 5 bezpečnostních problémů (CVE-2014-0231, CVE-2014-3523, CVE-2014-0117, CVE-2014-0118, CVE-2014-0226).
Ladislav Hagara | Komentářů: 2
21.7. 15:58 | Komunita
Projekt Ohloh (Wikipedia), informace a statistiky o otevřených softwarových projektech, byl přejmenován na Black Duck Open Hub. … více »
Ladislav Hagara | Komentářů: 3
20.7. 13:00 | Komunita
V New Yorku probíhá konference HOPE X. Jedná se o 10. konferenci HOPE (Hackers On Planet Earth). Konferenci je možné sledovat online (časový harmonogram). Videozáznamy proběhlých přednášek jsou k dispozici na Livestreamu (Manning, Serpico, Olson).
Ladislav Hagara | Komentářů: 5
18.7. 07:56 | Zajímavý článek
Díky Linux Foundation lze nahlédnout (YouTube) do domácí pracovny Linuse Torvaldse. Linus Torvalds mimo jiné předvádí svůj počítačový stůl spojený s běžeckým pásem (Treadmill desk).
Ladislav Hagara | Komentářů: 285
17.7. 22:42 | Pozvánky
GDG Prague a Inmite vás zvou na další zajímavý hackathon. Tentokrát se budou vytvářet aplikace pro chytré hodinky Android Wear, které byly představeny před měsícem na konferenci Google I/O. Na místě bude k dispozici několik hodinek na testování. Nejlepší aplikace mohou vyhrát zajímavé ceny. … více »
Destil | Komentářů: 0
17.7. 17:00 | Zajímavý článek
Pavel Tišnovský se v článku Textové editory ve Fedoře (1. část) na Fedora.cz věnuje konzolovým textovým editorům, jež jsou k dispozici nejenom ve Fedoře. Zabývá se editory e3, GNU nano, Jed, Joe a MCEdit (Midnight Commander Internal Editor).
Ladislav Hagara | Komentářů: 2
17.7. 11:28 | Nová verze
Keith Packard oznámil vydání X.Org Serveru 1.16. Nejnovější verze přináší integraci Glamoru a systemd, Glamor pro Xephyr, XWayland, podporu Non-PCI zařízení a odstraňuje tisíce varování překladače.
Ladislav Hagara | Komentářů: 25
16.7. 06:55 | Zajímavý software
Mozilla oznámila vydání Mozilla JPEG Encoder 2.0 (mozjpeg), knihovny pro zpracování obrázků ve formátu JPEG. Jedná se o fork knihovny libjpeg-turbo s cílem vylepšit kompresní poměr. Soubory vytvořené pomocí nové knihovny jsou v průměru o 5% menší. Knihovnu mozjpeg testuje a její vývoj podporuje také Facebook. Na další vývoj knihovny, vydání verze 3.0, přispěl částkou 60 tisíc dolarů.
Ladislav Hagara | Komentářů: 34
Máte na svém notebooku zašifrovaný pevný disk?
 (89%)
 (11%)
Celkem 6171 hlasů
 Komentářů: 45, poslední 21.7. 22:10
Rozcestník
Reklama
Autoškola testy online Levný benzín

Google Go v příkladech 1.

18. 5. 2011 | Jan Mercl | Programování | 4995×

Zahajujeme navazující seriál o programování v Go, tentokrát v příkladech. Ukázky se soustředí na malý (nebo jeden) okruh problémů a budou – i vzhledem k rozsahu článku/dílu seriálu – jen schematické.

Na druhé straně každá ukázka je v době odevzdání (Go se již mění pomaleji, ale ke změnám stále dochází) kompletní program, který je možno přeložit (pokud neukazuje úmyslně nepřeložitelnou chybu). Novinkou, přinejmenším snad v článcích o Go na AbcLinuxu, je možnost si na Go doopravdy „sáhnout“ a to i bez instalace jeho distribuce. Na domácí stránce Go je už nějaký čas tzv. Go playground. V něm je možné, v rámci některých pochopitelných omezení, zadávat a upravovat zdrojový kód v Go, následně jej nechat na vzdáleném serveru přeložit/sestavit a v případě úspěchu i provést. Pokud výsledný program úspěšně doběhne ve svém časovém limitu, zobrazí Go playground i vše, co zapsal program napsal do svého standardního výstupu.

Veškeré ukázky kódu jsou následovány odkazem, který příklad otevře v Go playgroundu. Tam je pak možné ukázku/program upravovat a nakonec klepnutím na tlačítko „COMPILE & RUN“ (nebo stiskem shift-enter) zkusit provést. Neověřoval jsem, ale předpokládám, že povolený Javascript bude nejspíše nutný. Pokud si „pískoviště“ zkusíte, může se Vám stát, že některá z dnešních ukázek bude hlásit timeout. Obvykle postačí ji v takovém případě zkusit provést ještě jednou, ale úspěch může záležet na zcela vnějších faktorech (možná dle okamžitého zatížení některého Google serveru), takže nic se v tomto směru nedá slíbit. Z diskuzí jinde pochází ještě jedna rada – někdy stačí v případě potíží (timeout provádění) jen pozměnit whitespace programu a tím ovlivnit použití kompilační cache playgroundu, která je v současné implementaci podezřelá, že je někdy příčinou problému.

V době odevzdávání článku se navíc ještě našla nemilá chyba (nahlášená), která se projevuje ve Firefoxu a (zatím) znemožňuje použití Go playground z FF. Doufejme, že chyba bude do doby vyjití článku opravena.

Obsah

Odlož paniku, vzchop se a jdi (defer panic, recover and go)

link

Příklad 1.

link
package main 

import "fmt"

func f(x int, c chan string) { 
    defer func() { 
        if e := recover(); e != nil { 
            c <- fmt.Sprintf("f(%d): %s", x, e) 
        } 
    }() 

    if x == 2 { 
        panic("x == 2 není podporováno") 
    } 

    c <- fmt.Sprintf("f(%d) == %d", x, 2*x) 
} 

func main() { 
    c := make(chan string) 
    for i := 1; i <= 2; i++ { 
        go f(i, c) 
        defer fmt.Printf("(%d) %s\n", i, <-c) 
    } 
} 

Upravit/Spustit

Výstup:

(2) f(2): x == 2 není podporováno
(1) f(1) == 2

Klíčové slovo go spustí provádění dané funkce/funkčního literálu v nové gorutině (ř.22). Gorutina nemůže volajícímu přímo nic vrátit (ve smyslu funkční hodnoty), volající navíc pokračuje bez čekání na ukončení gorutiny. Pokud chceme s paralelně prováděnou gorutinou komunikovat, je standardním Go idiomem použití komunikačních kanálů. V ukázce je kanál vytvořen na ř.20, funkce f (ř.5) standardně tímto kanálem odpovídá, gorutina jej získala jako argument volání. Na ř.16 odpovídá normálně a na ř.8 při výjimce (k té za chvíli).

Na ř.23 hlavní fuknce programu vypisuje výsledky vrácené gorutinami kanálem. V tomto případě pomocí odloženého příkazu klíčovým slovem defer (k němu opět za moment). Důležité je si uvědomit, že pokud funkce main() programu spustí libovolný počet gorutin, ale nijak nepočká na jejich provedení (tj. kdybychom třeba zakomentovali ř.23), tak celý program skončí svoje provádění dříve než budou mít další/jiné gorutiny příležitost dokončit svoji práci nebo ji dokonce vůbec zahájit. Možná se to bude někomu zdát jako zbytečná poznámka, ale v diskuzích na golang-nuts je tato chyba v dotazech začínajících programátorů v Go vidět dost často. Podobně chybné, jen opačně, je na konci main kvůli tomu např. psát nějaké zpoždění odhadovaného počtu sekund (třeba pomocí time.Sleep). Pokud je pro správnou činnost programu třeba nechat tu či onu gorutinu dokončit práci, je nutné se k takové události synchronizovat. Čekáním na příchod signálu/hlášení/výsledku kanálem je automaticky takovou synchronizací.

V dané ukázce by bylo možné čekat na známý počet hlášení (tj. 2) třeba v dalším cyklu. Na ř.23 využíváme pro automatické spárování potřebného počtu synchronizací příkaz defer. Jeho sémantika je jednoduchá – defer příkaz, kterým musí být volání funkce – způsobí zřetězení volání takové funkce těsně před návratem z funkce, ve které provádíme příkaz defer. Defer je možné vyvolávat opakovaně, odložené volání se koná v LIFO pořadí. Teprve až poté, co je celý tento „lokální zásobník“ vyprázdněn, dojde k návratu z funkce. V našem případě z funkce main, dojde proto k ukončení celého programu, leč řádně, až po ukončení práce obou (instancí) gorutiny f.

Právě popsaný mechanismus defer, zvláště pak skutečnost, že odložené příkazy se provedou ještě před návratem z dané funkce, se využívají pro ošetřování výjimek. Na ř.7 vidíme volání zabudované funkce recover, v rámci odloženého volání funkčního literálu na ř.6. Recover() vrací za běžných okolností nil. Pokud bylo normální provádění funkce ukončeno výjimkou, pak recover, použitý v odloženě vyvolané funkci, vrací aktuální chybový objekt. Protože recover voláme odloženě (ř.6), tak v případě výjimky, během provádění ř.8, „vidíme“ v uzávěře odložené funkce ještě platné parametry funkce f. Proto můžeme bez obav na ř.8 poslat kanálem c chybové hlášení. Kanál typu string je zde použit jenom pro zjednodušení příkladu, v main() se o obsah hlášení nijak nezajímáme, jen je vypíšeme.

Na ř.12 uměle vytváříme chybu, představte si pod tím obecný případ neplatného argumentu/stavu/jiné chyby. Bylo by zde možné opět přímo poslat něco do kanálu c a provést return. Pokud už ale máme ošetřeno pomocí defer zachytávání výjimek, je pohodlnější toto zachycení vyvolat jednoduše pomocí panic. Navíc takto zachytíme i neošetřenou výjimku z libovolné nižší úrovně provádění (vizte příklad 2). Argumentem panic je chybový objekt. Tato zabudovaná funkce je generická, tj. chybový objekt může být jakéhokoli typu. Pro změnu chování funkce dle typu chybového objektu vizte následující příklad.

Příklad 2.

link
package main 

import ( 
    "fmt"
    "os"
) 

func div(a, b int) int { 
    if b == -2 || b&0xff == 0xaa { 
        panic(fmt.Errorf("nepovolený argument %d", b)) 
    } 

    return a / b 
} 

var p *int 

func f(x int) (y *int, err os.Error) { 
    y = new(int) 

    defer func() { 
        if e := recover(); e != nil { 
            y = nil 
            err = e.(os.Error) 
        } 
    }() 

    switch x { 
    case -1: 
        *y = *p 
    case 2: 
        panic("TODO:f(2)") 
    default: 
        *y = div(0x12345678, x) 
    } 
    return 
} 

func main() { 
    for i := -3; i <= 3; i++ { 
        v, err := f(i) 
        if err != nil { 
            fmt.Printf("f(%d) – %s\n", i, err) 
            continue 
        } 

        fmt.Printf("f(%d) == %d\n", i, *v) 
    } 
}

Upravit / Spustit

Výstup:

f(-3) == -101806632
f(-2) – nepovolený argument -2
f(-1) – runtime error: invalid memory address or nil pointer dereference
f(0) – runtime error: integer divide by zero
f(1) == 305419896
panic: TODO:f(2) [recovered]
    panic: interface conversion: string is not os.Error: missing method String

runtime.panic+0xac /tmp/sandbox/go/src/pkg/runtime/proc.c:1060
    runtime.panic(0x45a1f0, 0xf84001fd90)
itab+0x101 /tmp/sandbox/go/src/pkg/runtime/iface.c:134
    itab(0x4547b0, 0x43ec38, 0x0, 0xf84003e048, 0x1, …)
runtime.ifaceE2I+0xe3 /tmp/sandbox/go/src/pkg/runtime/iface.c:473
    runtime.ifaceE2I(0x4547b0, 0x43ec38, 0xf840001320, 0x2b42b055cdf8, 0xf84000b780, …)
runtime.assertE2I+0x43 /tmp/sandbox/go/src/pkg/runtime/iface.c:488
    runtime.assertE2I(0x4547b0, 0x43ec38, 0xf840001320, 0xf84000b7b0, 0xf840001320, …)
main._func_001+0x75 /tmpfs/gosandbox-5522aa24_eb79397b_f981defe_0fef1eaf_56f2c89a/prog.go:24
    main._func_001(0xf8400000b0, 0xf840001330, 0x401f4f, 0x2b42b055c100, 0x2b42b055cfb8, …)
----- stack segment boundary -----
runtime.panic+0xf6 /tmp/sandbox/go/src/pkg/runtime/proc.c:1041
    runtime.panic(0x43ec38, 0xf840001320)
main.f+0x114 /tmpfs/gosandbox-5522aa24_eb79397b_f981defe_0fef1eaf_56f2c89a/prog.go:32
    main.f(0x2, 0x642528660000000c, 0xf84000c740, 0x200000002, 0x12, …)
main.main+0x39 /tmpfs/gosandbox-5522aa24_eb79397b_f981defe_0fef1eaf_56f2c89a/prog.go:41
    main.main()
runtime.mainstart+0xf /tmp/sandbox/go/src/pkg/runtime/amd64/asm.s:77
    runtime.mainstart()
runtime.goexit /tmp/sandbox/go/src/pkg/runtime/proc.c:178
    runtime.goexit()
----- goroutine created by -----
_rt0_amd64+0x8e /tmp/sandbox/go/src/pkg/runtime/amd64/asm.s:64

Tato ukázka rozvíjí příklad 1 v oblasti výjimek. Na ř.10 vyvoláváme výjimku ve funkci div, zachytává se ale o úroveň výše, na ř.22 ve funkci f. Na ř.13 budeme občas dělit nulou bez kontroly, odchycení je ale stejné. Funkce f (ř.18) je modelová funkce vracející ukazatel a příznak chyby. Na ř.19 je častý případ, kdy na počátku provádění funkce vytváříme nový objekt (alokace). V případě zachycení výjimky chceme místo ukazatele na objekt zajistit (bezpečnější) vrácení hodnoty nil, to zajišťuje ř.23. Na ř.30 občas způsobíme další typ výjimky – dereferenci nil ukazatele. Na ř.32 opět občas „zpanikaříme“, tentokrát úmyslně s chybovým objektem odlišného typu, v tomto případě string. Na ř.24 totiž provádíme run time typovou kontrolu (type assertion) chybového objektu e. Pro typ string tato kontrola selže, způsobí opět další výjimku, která už ukončí běh celého programu. To je modelové schéma, kdy potřebujeme rozlišit výjimky, které vracíme volajícímu jako chybu (s nadějí na zotavení programu) a situace, kdy pokračovat nelze – zde modelově vstupujeme do části kódu, který je teprve třeba napsat. Proto nám ve výstupu neprojdou všechny hodnoty cyklu z ř.40 a pro i == 2 program skončí neošetřenou chybou a tedy výpisem zásobníku.

Vracení chyby typu os.Error je záležitost víceméně (ustáleného) zvyku. Na druhé straně os.Error není statický typ, je to rozhraní, takže v případě potřeby jemnějšího rozlišení kategorií chyb nebo když je nutné různé chyby doplnit o přidané informace – nám nic nebrání použít uživatelsky definovaný typ. Stačí bude‑li implementovat jedinou metodu rozhraní os.Error – String(), tj. převod na řetězec.

Všechny typy jsou si rovné, ale některé jsou si rovnější

link

Příklad 3.

link
package main 

type bad interface{} 

func (b bad) foo() { 
    println("Hi from bad") 
} 

type ok interface { 
    foo() 
} 

type bar struct{} 

func (b bar) foo() { 
    println("Hi from bar") 
} 

func main() { 
    var iface bad 
    iface.foo() 
    bar{}.foo() 
} 

Upravit / Spustit

Výstup:

prog.go:5: invalid receiver type bad
prog.go:21: iface.foo undefined (type bad has no field or method foo)

Všechny pojmenované typy v Go mohou mít k sobě přidružené metody. Jednou z „optických“ ne ortogonalit tohoto pravidla je to, že typ rozhraní může metody pouze deklarovat avšak nikoli implementovat. Pro všechny ostatní typy je tomu právě naopak. Příklad 3 na ř.5 implementuje metodu rozhraní bad (ř.3) a to nám kompilátor nedovolí. Jako cvičení si lze vyzkoušet uvést tento příklad do přeložitelného stavu.

Ještě jedna (po)drobnost omezuje typy, ke kterým je možné definovat metody. Typ (přijímače metody) může být sám o sobě ukazatelem (ukazatelovým typem), ale jím odkazovaný typ už ukazatelem být nesmí. Vizte též specifikaci.

Třikrát totéž není totéž

link

Říká se, vcelku oprávněně, že je dobré, když jedna sémantická konstrukce je v programovacím jazyce vyjádřitelná jenom jedním způsobem. Podíváme se nyní na tři verze skoro stejného schématu. Úmyslně je v Go napíšeme různými způsoby. Myslím ale, že v žádném příkrém rozporu s první větou tohoto odstavce nebudeme. Různé implementace v tomto případě přinášejí ne zcela shodnou sémantiku – byť rozdíly jsou, dle úhlu pohledu, spíše jen v menších detailech. Každá implementace se ale hodí pro trochu jinou situaci. Představme si třeba rozdíl mezi situací kdy jsme odkázáni na použití existující funkce/metody třetích stran vs. stav, kdy si „operátor“ můžeme/chceme a/nebo musíme napsat sami.

Modelové schéma v našem případě je nějaká abstraktní operace nad adresářovým stromem souborového systému, přesněji řečeno provedení nějaké činnosti nad jednotlivými adresáři stromu. Kdo chce, může v tom vidět i Visitor pattern. Ve standardní knihovně existuje funkce filepath.Walk, kterou se zde inspirujeme. Pro jednoduchost degenerujeme procházení stromu na návštěvu pouze jeho kořene a modelově chceme jedním mechanismem získávat dvě různé informace – počet souborů v adresáři nebo jejich celkovou velikost. Další možnosti konkrétní „operace“ (třeba v duchu příkazů cat, echo, mv, …) si jistě lze domyslet.

Příklad 4a.

link
package main 

type visitor func(string) 

func files(dir string) { 
    println(dir, "obsahuje celkem 42 souborů") 
} 

func bytes(dir string) { 
    println(dir, "obsahuje celkem 524287 bajtů") 
} 

func walk(path string, v visitor) { 
    v(path) 
} 

func main() { 
    walk("/", files) 
    walk("/bin", bytes) 
} 

Upravit / Spustit

Výstup:

/ obsahuje celkem 42 souborů
/bin obsahuje celkem 524287 bajtů

Příklad 4a je, volně řečeno, ve stylu Cčka. Bez použití (možnosti použití) rozhraní nebo třeba virtuálních metod objektů je použití funkčního typu pro „operaci“ jednoduchým řešením – a v případě C víceméně také jediným. Pomíjíme zde nepoměrně složitější možnosti, které přináší třeba GObject, protože to už nehovoříme o jazyku, ale o jeho knihovně. Ostatně nějaký mechanismus jako vtable a vcall jde s konečným úsilím implementovat snad vždy i v ne OOP programovacím jazyku.

Řešení (schématu) je zcela nekomplikované, jediná deklarace (funkčního typu visitor na ř.3), použitá v definici funkce walk na ř.13, je zde „nutná“ navíc jen v rámci snad dobrého stylu. Typ parametru 'v' by mohl být definován i typovým literálem – lze si ověřit na „pískovišti“ (nezkusíte si to?).

Příklad 4b.

link
package main 

type visitor interface { 
    visit() 
} 

type files string 

func (dir files) visit() { 
    println(dir, "obsahuje celkem 42 souborů") 
} 

type bytes string 

func (dir bytes) visit() { 
    println(dir, "obsahuje celkem 524287 bajtů") 
} 

func walk(path visitor) { 
    path.visit() 
} 

func main() { 
    walk(files("/")) 
    walk(bytes("/bin")) 
} 

Upravit/Spustit

Výstup:

/ obsahuje celkem 42 souborů
/bin obsahuje celkem 524287 bajtů

Příklad 4b představuje obvyklý přístup, který by se asi dal nazvat Go idiomatický. Ostatně toto řešení je (schématicky) identické implementaci svého vzoru (vizte filepath.Walk a rozhraní filepath.Visitor). Na ř.3 deklarujeme rozhraní. Na ř.7 a 13 deklarujeme pojmenované typy, které toto rozhraní implementují (ř.9 a 15). Na ř.24 a 25 provádíme konverzi literálu typu string na typ files resp. bytes a tím volíme „operaci“, kterou od funkce walk požadujeme. Konverze je zde použita jen pro zkratku příkladu, jistě si snadno domyslíte obecnější případ entit různých typů.

Příklad 4c.

link
package main 

type visitor func(string) 

func (v visitor) visit(dir string) { 
    v(dir) 
} 

func (v visitor) walk(path string) { 
    v.visit(path) 
} 

var files visitor = func(dir string) { 
    println(dir, "obsahuje celkem 42 souborů") 
} 

var bytes visitor = func(dir string) { 
    println(dir, "obsahuje celkem 524287 bajtů") 
} 

func main() { 
    files.walk("/") 
    bytes.walk("/bin") 
} 

Upravit / Spustit

Výstup:

/ obsahuje celkem 42 souborů
/bin obsahuje celkem 524287 bajtů

V příkladu 3 jsme si připomenuli, že metody může implementovat každý (pojmenovaný) typ, který není rozhraní. V příkladu 4c využijeme jeden, možná trochu překvapivý, důsledek tohoto pravidla. V Go můžou mít funkce metody, korektně řečeno – metody lze implementovat i pro (pojmenovaný) funkční typ. Autor nezná dostatečně dobře dostatečný počet jiných programovacích jazyků aby mohl posloužit příkladem „stejně/podobně jako jako v jazyce X“, jen odhaduje, že něco podobného by možná šlo „spáchat“ přinejmenším v Javascriptu?

Tato implementace nejvíce připomíná styl funkčních jazyků. Na ř.3 deklarujeme funkční typ visitor. Mimochodem deklarace je zcela stejná jako „C“ verzi v příkladu 4a. Na ř.5 a 9 definujeme metody typu visitor. Na ř.13 a 17 deklarujeme proměnné files a bytes typu visitor, v obou případech s inicializátorem pomocí funkčního literálu. Toto je implementační detail, mohli bychom definovat obyčejné funkce (s podpisem shodným s typem visitor), pak by ovšem přístup k jejich metodám byl možný pouze po konverzi ve stylu:

func files(dir string) { 
    println(dir, "obsahuje celkem 42 souborů") 
}

//...

visitor(files).walk("/") 

Mírně složitější verze s funkčním inicializátorem, použitá v příkladu 4c, se vyplatí, pokud budeme takovou funkci, tedy přesněji metody takového funkčního typu, volat častěji, protože taková volání jsou potom krátká a dobře čitelná jak vidno na ř.22 a 23.

Příklad 4c způsobuje v této zkratkovité podobě kontroverzní reakce – minimálně u kolegy, který Go nepoužívá, ale je ochotný tyto články před odevzdáním číst a kontrolovat. Podstatně podrobněji se tomuto „triku“ věnuje část Effective Go – Interface methods, na konci oddílu v diskuzi typu HandlerFunc a jeho metody ServeHTTP. Celý mechanismus popsaný v posledně uvedeném odkazu se reálně používá ve standardní knihovně.

Na závěr

link

Pokračování by mělo vyjít snad za měsíc. Bude-li mít někdo z čtenářů zvláštní zájem o nějaké téma ke zpracování pak nechť dá prosím vědět s dostatečným předstihem.

Laboratoře CZ.NIC

O autorovi

Jan Mercl, autor textu, pracuje v Laboratořích CZ.NIC jako programátor pro výzkum a vývoj.

       

Hodnocení: 100 %

        špatnédobré        

Nástroje: Tisk bez diskuse

Tiskni Sdílej: Linkuj Jaggni to Vybrali.sme.sk Google Del.icio.us Facebook

Komentáře

Vložit další komentář

18.5.2011 08:26 ...
Rozbalit Rozbalit vše Re: Google Go v příkladech 1.
Zaujimavy pohlad: http://www.lessonsoffailure.com/software/google-go-good-for-nothing/
18.5.2011 13:03 vlastagf | skóre: 11
Rozbalit Rozbalit vše Re: Google Go v příkladech 1.
Mně se ze začátku Go vůbec nelíbilo, ale na druhou stranu jsem před pár dny nahodil kompilátor a když je čas, tak koukám na tutoriály. Co se mi moc líbí a rozčiluje mně na C++.

a) implicitní konverze, proč tohle vůbec někoho napadlo? je to úplně proti duchu C++, kde si programátor všechno hlídá sám

b) neuvěřitelně pomalá kompilace - píšu teď něco většího nad msvc, linkuju pár knihoven a je to děs

c) dynamické linkování 1) možná to šetří místo v paměti, když víc aplikací používá stejnou knihovnu, ale jedna může s novější verzí přestat fungovat 2) dá se upravit aplikace jen updatem knihovny, ale stejně jednoduše se dá rebuildnout

d) ta paralelizace vypadá dobře, člověk má uplně chuť to tak psát, v C++ jsem zkoušel TBB a Boost::Thread a nedá se to srovnat

e) líbí se mi kopírování hodnotou, to se mi zas nikdy nelíbilo na Jávě a C#

z) ale nelíbí se mi pevné formátování, to jsem nesnášel u Haskellu, nemám to rád u Pythonu a nebudu to mít rád ani tady. a ke všemu to asi udělali jen kvůli rychlejšímu parsování a jednodušší podpoře interpretování

y) a kdyby se dal občas vypnout GC a člověk by po sobě uklízel sám, to bych se taky nezlobil, nemluvě o podpoře assembleru
18.5.2011 13:54 jnml
Rozbalit Rozbalit vše Re: Google Go v příkladech 1.
y) a kdyby se dal občas vypnout GC a člověk by po sobě uklízel sám, to bych se taky nezlobil, nemluvě o podpoře assembleru
Tělo Go funkce může být (externě) napsáno v assembleru.
Specs: Function declarations
Příklad: src/pkg/big
18.5.2011 20:03 Ondřej Surý | skóre: 14 | Praha
Rozbalit Rozbalit vše Re: Google Go v příkladech 1.
Ad C) od toho máme v rozumných systémech SONAME a rozumní autoři knihoven jej i používají.
Nehledejte zlý úmysl tam, kde je dostatečným vysvětlením hloupost.
19.5.2011 18:06 Ivan
Rozbalit Rozbalit vše Re: Google Go v příkladech 1.
Popripade jeste existuje verzovani symbolu vramci jedne knihovny.
19.5.2011 21:08 Ondřej Surý | skóre: 14 | Praha
Rozbalit Rozbalit vše Re: Google Go v příkladech 1.
Pravda na to jsem úplně zapomněl a při tom to v Debianních balíčcích docela používám... Akorát ještě aby to taky používali autoři knihoven :(
Nehledejte zlý úmysl tam, kde je dostatečným vysvětlením hloupost.
vain avatar 18.5.2011 09:05 vain | skóre: 15
Rozbalit Rozbalit vše Re: Google Go v příkladech 1.
Hm.. tak v tom číst tedy neumím. Když se podívám na C++, C#, Javu, Python apod... tak chápu o co jde a co znamená co, ale tohle je humáč ;-)
If the only choice you've got is to do the wrong thing, then it's not really the wrong thing, it's more like fate.
18.5.2011 12:07 salam
Rozbalit Rozbalit vše Re: Google Go v příkladech 1.
Nesnáším otevírací závorku na konci řádku, zhoršuje to výrazně přehlednost a neplní základní funkci - otevírací a zavírací závorka jsou ve stejném sloupci (to při velkém zanoření dost pomáhá). S tímto zápisem jde o python :-)
Solitary avatar 18.5.2011 12:41 Solitary
Rozbalit Rozbalit vše Re: Google Go v příkladech 1.
Nesouhlasim, dle meho jde o dost subjektivni nazor... pokud nejsi prase a odsazujes (nemusi jit o Python, spravne odsazovat by se melo ve vsech jazycich), tak ve stejnem sloupci jako uzaviraci zavorka bude radek kde zacina dana metoda. Oteviraci zavorka na konci radku je pak nepodstatna a usetris radek v kodu. Naopak, na novem radku, ji zase nesnasim ja, dle meho to prehlednosti neprida (pribude radek) a navic to vytvari dojem, ze dana metoda k bloku nepatri.
Bystroushaak avatar 18.5.2011 13:27 Bystroushaak | skóre: 23 | blog: Bystroushaakův blog | Praha
Rozbalit Rozbalit vše Re: Google Go v příkladech 1.
Pod tohle se můžu podepsat, mám úplně stejný názor.
Poté, co mi došlo, že nejsem génius, rozhodl jsem se zešílet. ## Life In A Day
vain avatar 18.5.2011 13:31 vain | skóre: 15
Rozbalit Rozbalit vše Re: Google Go v příkladech 1.
Také souhlas.
If the only choice you've got is to do the wrong thing, then it's not really the wrong thing, it's more like fate.
18.5.2011 17:13 salam
Rozbalit Rozbalit vše Re: Google Go v příkladech 1.

Ano, když něco nesnáším, jde o můj subjektivní názor - to snad není třeba komentovat... :-)

Já často spojuji velké bloky zdrojáků z různých zdrojů a časů a tam přeskok na párovou závorku a letmá kontrola čísla sloupce hodně pomáhá, používám to prakticky denně. A dále - pokud je řádek delší než zobrazený text, pak se tato závorka dostane mimo obrazovku a já pak musím při vizuální kontrole spoléhat na to, že to je dobře odsazené. Jenže pokud se ke mne dostane zdroják, kde jsou mixované tabulátory a mezery a já mám tabulátory nastavené na jinou hodnotu než autor... Prostě python :-) :-)

To ušetření volného řádku nějak nechápu - co přesně se tím ušetří? Možná na malém monitoru, rozlišení.. No a ten dojem, že řádky následující za začátkem bloku do něj nepatří, tak to bude nejspíš ten 'dost subjektivní názor' ;-)

Bystroushaak avatar 18.5.2011 17:28 Bystroushaak | skóre: 23 | blog: Bystroushaakův blog | Praha
Rozbalit Rozbalit vše Re: Google Go v příkladech 1.
No a ten dojem, že řádky následující za začátkem bloku do něj nepatří, tak to bude nejspíš ten 'dost subjektivní názor' ;-)
No, to jo, ale když vidím tu závorku na novém řádku, působí to nemocně.

Jinak ať žije autoformater :)
Poté, co mi došlo, že nejsem génius, rozhodl jsem se zešílet. ## Life In A Day
18.5.2011 17:49 salam
Rozbalit Rozbalit vše Re: Google Go v příkladech 1.

Pro mě je nemocná ta 'schovaná' a "nepodstatná" závorka, která tak ztrácí část své funkčnosti. Ale určitě souhlasím, že čtení je věc zvyku. Problém je v tom, že ve své práci jsem ten autoformater často já sám.

Tonocí ve zdrojáku se i závorky chytá...

Solitary avatar 18.5.2011 18:52 Solitary
Rozbalit Rozbalit vše Re: Google Go v příkladech 1.
Nekomentoval jsem tvuj nazor, ze je subjektivni (ten samozrejme je), ale to, ze nahled na danou problematiku je vzdy subjektivni a kazdy se k tomu stavi jinak. Kdyz mas kod tak dlouhy, ze presahuje sirku obrazovky, tak by mozna bylo na miste ho rozlozit na vic radku... ono kdyz neni videt kus kodu, tak se to cte blbe tak ci onak. Hlavni duvod, proc si myslim, ze je lepsi davat zavorku hned za danou metodu je ten, ze je jasne, ze ten blok kodu k tomu patri a nejde o nejaky samostatny blok.
if(true) do();
{
//blok kodu
}
A presne v tuhle chvili by dle meho bylo velmi snadne treba prehlidnout nenapadnou metodu do() a myslet si, ze ten blok patri k podmince (zrovna treba ten pripad, kdy by vyraz v podmince byl delsi nez je sirka monitoru). Je to extrem, ale je to vec, ktera me vadi :) navic ta rozlezlost - ten radek navic me proste irituje :) je takovy chudak opusteny a vypada to, ze se k nicemu nevaze... (v tomto pripade se opravdu nevaze, a pokud bys prehledl do() tak si toho tak lehce nevsimnes)
18.5.2011 18:59 Roger
Rozbalit Rozbalit vše Re: Google Go v příkladech 1.
Tohle resi
if (true)
  do();
prip. rovnou
if (true)
{
  do();
}
coz dost pomaha, pokud nechcete hledat nahodnou chybu ve ctyri rano pred odevzdanim...
Solitary avatar 18.5.2011 19:16 Solitary
Rozbalit Rozbalit vše Re: Google Go v příkladech 1.
Tak samozrejme... osobne pouzivam novy radek a i zavorky u techto jednoduchych vyrazu (az na vyjimky, kdy jsem rozmarny :-) ale nikdy na ukor prehlednosti), byl to jen pripad, ktery by mohl nastat a pri tomto zapisu byt problematicky. Ono totiz ne vzdy musime cist kod, ktery jsme sami napsali, a pokud nekdo pise takto a udela neco podobneho, tak muze byt problem na svete. V pripade zapisu s oteviraci zavorkou na konci vyrazu to prakticky nehrozi.
18.5.2011 21:25 Roger
Rozbalit Rozbalit vše Re: Google Go v příkladech 1.
Jo, s tim blokem u ifu to byla vlastni (horka) zkusenost - kolega napsal
if (neco) { blok; } else prikaz;
a pak chtel pred prikaz doplnit ladici vypis, ale zapomnel puvodni prikaz u else dat do bloku, takze vypadl mimo if/else :( Od te doby jsem opatrny, a - kdyz nejsem rozmarny :) - radeji zavorkuju kde co.

Taky, pokud treba odnekud kopiruju jen kus kodu a neupravuju cizi projekt, pouzivam formatovani v editoru - pak mam jakz-takz jistotu, ze se v tom da vyznat.

Na druhou stranu - treba v jave pisu zavorky na konec, tam je to standard (a NB to tak automaticky formatuji :) ). Naopak MSVS formatuje tak, jak popisuju nahore.

Zatim jsem se z toho jeste nezblaznil. Aspon myslim :)
vlk avatar 18.5.2011 19:17 vlk | skóre: 21 | blog: u_vlka
Rozbalit Rozbalit vše Re: Google Go v příkladech 1.

takze v praci asi budes plateny od poctu riadkov, ze?

You don't exist, Go away !
18.5.2011 23:40 __dark__
Rozbalit Rozbalit vše Re: Google Go v příkladech 1.
Každý normální programátor by před tu složenou dal mezeru. Ten váš výpis mi připadá spíš jako nějaký výstup z autoformateru, který nepřemýšlí (mimochodem normální programátor snad autoformát ani nepotřebuje). Já osobně mám rád složené závorky na samostatný řádek - nikdy mi nepřekážel větší kód, který je čitelný.
19.5.2011 10:52 salam
Rozbalit Rozbalit vše Re: Google Go v příkladech 1.

Pokud někdo formátuje zdroják takto, pak je jen na místě, aby si problémy s tím spojené pěkně odladil. Nepamatuji si ale, že bych při práci někdy viděl něco podobného v takové pozici, že by to znamenalo programátorovu chybu. Samozřejmě, že tam pro lepší čitelnost patří odřádkování a klidně bych uvítal komentář, proč je tam ten extra blok.

Já, když už při své práci více zasahuju do cizího kódu (oprava chyby), tak ho většinou poměrně dost lokálně asimiluju a tuhle (pozor nasleduje subjektivní názor ;-)) chybu formátování okamžitě opravuju, stejně jako závorky na konci řádků, velmi dlouhé řádky (to si okamžitě zvětším okno, případně zmenším písmo), chybějící odřádkování, někdy dokonce absence formátování...

Dělám v týmu, ve kterém převážně vždy dodržujeme několik jednoduchých pravidel. Jedno z nich je primitivní: za if, for, while... se nemá schovávat NIC.

Mini anketa: já mám běžně nastavenou velikost okna tak, že vidím ze zdrojáku 50 řádků po 150 znacích. Kolik máte vy?

18.5.2011 20:02 Ondřej Surý | skóre: 14 | Praha
Rozbalit Rozbalit vše Re: Google Go v příkladech 1.
Koukám, že se svět stále nezbořil a komentáře pod článkem o Go stále ve většině případů nejsou ani trochu blízko obsahu článku.

Ale je pravda, že zatím mi tady chybí 'D'.
Nehledejte zlý úmysl tam, kde je dostatečným vysvětlením hloupost.

Založit nové vláknoNahoru

ISSN 1214-1267   Powered by Hosting 90 Server hosting
© 1999-2013 Argonit s. r. o. Všechna práva vyhrazena.