Co mě zaujalo na Google Go?

Logo
jazyka GoPřed několika dny Google vydal nový programovací jazyk Go (i když kdo ví, jestli se třeba nakonec nebude jmenovat jinak). Je určený pro systémové programování, je typově bezpečný (žádná ukazatelová aritmetika), paměť v něm spravuje garbage collector a obsahuje zabudovanou podporu pro paralelizaci.

Protože nové jazyky já rád, Go jsem samozřejmě prozkoumal a nabízím malý přehled toho, co mě na něm zaujalo. Snažil jsem se vybrat především věci, kterými se Go liší od jiných podobných jazyků, a zaměřil jsem se spíš na high-level záležitosti než na drobné detaily.

Zajímavé aspekty Go

Cíl

Cílem Go je usnadnit a zefektivnit systémové programování a přiblížit ho dnešním dynamickým jazykům. Ty nejsou zdaleka tak výkonné a typově bezpečné jako statické jazyky, ale mnohem snáz se v nich programuje, a tak k nim programátoři utíkají.

Osobnosti tvůrců

Myšlenkovými otci Go jsou mimo jiné Rob Pike a Ken Thompson. Tito pánové jsou zodpovědní za programovací jazyk C, operační systémy Unix a Plan 9 a také kódování UTF-8. Všechno poměrně dobře navržené a (až na Plan 9) i praktické a dodnes široce používané věci.

Rychlá kompilace

Kompilátor Go je ďábelsky rychlý – celá standardní knihovna se například zkompiluje za několik sekund. Rychlosti dociluje mimo jiné dvěma prostředky: efektivní prací se závislostmi jednotlivých částí programu a jednoduchou gramatikou jazyka.

Závislosti je v programu nutné explicitně deklarovat a kompilátor pak s těmito deklaracemi pracuje – především chytře zpracovává tranzitivní závislosti. Může tak při kompilaci a linkování krom zdrojového kódu načítat jen minimum souborů.

Jednoduchá gramatika jazyka nezrychluje jen kompilaci, ale zjednodušuje i další nástroje na práci s kódem (IDE, refaktorizační nástroje, tvůrce dokumentace aj.). V neposlední řadě je program přehlednější pro programátora. Autoři se zjevně poučili z příkladu C++, jehož parser je téma na diplomku.

Typový systém

Autoři vycházeli ze dvou myšlenek: je dobré důsledně oddělit rozhraní a implementaci a je špatné nutit programátory uspořádávat své třídy do hierarchií.

Obě myšlenky vedou k pojmu interface, který je v Go chápán jako množina metod. Jeho implementace je jakýkoliv typ, který danou sadu metod obsahuje. Podstatné je, že implementaci interfacu není nutné nijak deklarovat, vzniká implicitně na základě pouhé shody názvů a signatur metod. Velmi to připomíná duck typing známý z dynamických jazyků.

Zajímavá je práce s metodami: jsou to v podstatě obyčejné funkce, které mají jeden speciální parametr – příjemce. Jeho typ je chápán jako typ, ke kterému metoda patří. Není nutné, aby příjemce byl objekt (ty ostatně v Go jako prvek jazyka neexistují) – je tak možné definovat metody na jakémkoliv datovém typu a následně je volat na jeho hodnotách klasicky "přes tečku":

/* Definice typu Point */
type Point struct {
  X, Y float
}

/* Definice metody Scale na typu Point */
func (p *Point) Scale(factor float) {
  p.X *= factor;
  p.Y *= factor;
}

/* Použití */
x := &Point{ 3, 4 };
x.Scale(5);
Přímá podpora paralelizace v jazyce pomocí goroutines

Goroutines jsou běhová primitiva na rozhraní mezi procesem, vláknem a korutinou. Komunikace mezi nimi probíhá pomocí kanálů, inspirovaných formalismem CSP. Pokud aspoň trochu znáte Erlang, budou vám goroutines povědomé.

Goroutines jsou hlavní mechanismus, pomocí kterého je v Go podporována paralelizace. Runtime jazyka pracuje s goroutines velmi efektivně, není problém mít spuštěných například několik tisíc goroutines najednou.

Zajímavé je, že kanály, kterými goroutines komunikují, jsou úplně obyčejné hodnoty (jako třeba čísla či řetězce), takže je jde mimo jiné třeba také poslat kanálem :-)

Go nepodporuje spoustu běžných konceptů

Generiky/šablony, výjimky, aserce, přetěžování metod, přetěžování operátorů, implicitní numerické konverze... to vše v Go nenajdete. Důvodem je jednoduchost jazyka nebo negativní zkušenosti autorů s těmito konstrukcemi. Podrobněji je vše rozepsáno v dokumentaci.

Kód je povinně v UTF-8

Podpora Unicode je dnes u nových jazyků samozřejmost, ale Go je zajímavý tím, že zdrojový kód je vždy v kódování UTF-8. Odpadají tím zmatky při určení kódování zdrojového kódu, obvyklé u jiných jazyků.

Utilita gofmt

Autoři Go vyřešili všechny debaty ohledně stylu psaní kódu! Napsali totiž pretty-printer gofmt, který kód zformátuje do jednotné podoby. Je to poměrně sofistikovaný nástroj a řeší třeba i takové detaily jako správné odsazení komentářů za položkami struktury. Všechen zdrojový kód knihoven v Go je pomocí gofmt zformátován. Pokud má prý nějaký vývojář proti výsledku námitky, má je řešit s autory gofmt :-)

A co mě naopak nezaujalo?

Syntaxe

Syntaxe Go v zásadě vychází z céčka, ale obsahuje poměrně dost změn – kromě modifikací a nových prvků vynucených jazykem jde především o úpravu formátu deklarací (dle mého názoru dost nepovedenou) a nepovinné středníky a závorky na některých místech.

Bohužel syntaxe Go na mě dělá dojem jakéhosi hybridu – jako by se autoři snažili céčkovou syntaxi zpřehlednit a vyčistit od nepotřebných prvků, ale zároveň se nechtěli oprostit od klasických složených závorek. Navíc do syntaxe zavedli několik nehezkých věcí (například zbytečný operátor := a další význam závorek). Program napsaný v Go tak není příliš příjemný na čtení a nevypadá hezky.

Standardní knihovna

Autoři jsou zjevně zvyklí na céčko se svými spartánskými názvy a tak podobný styl na mnoha místech zachovali i v knihovnách Go. Já dávám přednost větší deskriptivnosti. Po stránce návrhu a funkcionality jsem knihovnu příliš nezkoumal.

Celkový dojem

Celkově mám z Go rozporuplný pocit. Na jednu stranu obsahuje řadu zajímavých myšlenek, ale na druhou stranu se autorům příliš nepovedla syntaxe a učinili řadu řekněme zvláštních návrhových rozhodnutí. Do jazyka také zavedli několik vyložených podivností (namátkou třeba určení viditelnosti metody podle velikosti prvního písmene jejího názvu, nebo konstrukce iota). Mít na výběr, tak bych v Go programovat asi spíš nechtěl.

Kde se dovědět víc?

Spousta dokumentace se dá najít na webu jazyka, přičemž nejzajímavější je asi Language Design FAQ. Pokud máte cca hodinu čas, doporučuju shlédnout hodinovou přednášku o Go přímo od jednoho z tvůrců: