Гоу () је програмски језик отвореног кода настао у Гуглу 2007. године. Језик су осмислили Роберт Грисемер, Роб Пајк и Кен Томпсон, а намењен је првенствено системском програмирању. Ослањајући се на традицију језика C и Паскал, језик је компилиран, са статичким типовима података, ограниченим структурним типовима, садржи аутоматско управљање меморијом и функционалности за конкурентно програмирање инспирисане комуницирајућим секвенцијалним процесима.
Почетак рада на језику је септембар 2007. године. Званично је промовисан новембра 2009. године под модификованом -{BSD}- лиценцом. Данас се користи за мрежне програме, најпре у оквиру Гуглових система, али и у другим компанијама. Постоје две главне имплементације језика: gc, који је главна имплементација коју је развио Гугл и gccgo из ГНУ колекције компајлера. До верзије 1.5, gc имплементација је била написана у мешавини C, асемблер и Гоу кода, а од верзије 1.5, C код је преведен у Гоу.
Историја
Језик је настао као експеримент тројице Гуглових запослених—Роберт Грисемер, Роб Пајк и Кен Томпсон. Идеја је била да се осмисли нови језик за системско програмирање који би решио главне проблеме постојећих језика такве врсте а притом задржао њихове позитивне особине. Видео снимак доступан. Нови језик би имао следеће особине: био би статички компилиран и могао би да се се користи за велике системе (као Java и C++), брз развој читљивих програма, без превише обавезних кључних речи (као код динамичких језика), не би захтевао компликоване алате, већ би подржао шири скуп једноставних алата подржавао би мрежно и конкурентно програмирање
У интервјуима, тројица дизајнера су изразила да нису љубитељи сложености C++-а, и да је то била главна мотивација за дизајнирање новог језика.
Дизајн језика
Највећи утицај на дизајн језика су језици из породице C и Паскал. Они се од ових језика разликују по додацима који побољшавају концизност, једноставност и безбедност програма.
Кратак преглед особина које карактеришу Гоу: Синтакса и окружење које прихвата идеје које се чешће срећу у динамичким језицима. Опциона скраћена декларација и иницијализација променљивих кроз локално закључивање типова података (; i := 0 уместо int i = 0;). Брза компилација програма у извршну датотеку. Једноставно управљање пакетима (go get).Download and install packages and dependencies - go - The Go Programming Language; видети godoc.org за адресе и документацију појединих пакета, као и једноставна и читљива документација пакета на интернету Јединствени приступи проблемима: Уграђене функционалности за конкурентно програмирање: лаки процеси (корутине - -{goroutines}-), канали за ток података између процеса, и select кључна реч за управљање каналима. Систем интерфејса и уграђивања типова уместо уместо виртуалног и невиртуалног наслеђивања. Скуп алата који производи статичке извршне датотеке које не зависе од динамичких библиотека. Тежња ка једноставности језика - спецификација је довољно кратка да програмери могу целу да је запамте.Роб Пајк на подкасту Изворне датотеке са кодом су увек кодиране као UTF-8, што омогућује локализовање коментара и документације, али и имена типова, функција, променљивих и константи.
Гоу је често мета следећих критика: Недостатак генеричких типова доводи до дупликације кода. Може се симулирати уз помоћ метапрограмирања и рефлексије, али се тада губи на перформансама и провери тачности типова. Стандардна библиотека из тог разлога не нуди генеричке алгоритме. Нема могућности проширивања језика (на пример, кроз додавање оператора за корисничке типове), па одређени задаци захтевају више кода. Једноставан систем типова који није базиран на Хиндли-Милнер систему смањује безбедност и једноставност програма. Аутоматско управљање меморијом узрокује паузе у раду програма, па то умањује могућност примене у системским програмима, у поређењу са језицима у којима се ручно управља меморијом.
Дизајнери језика тврде да су ови недостаци важни за успех језика, и детаљно објашњавају зашто су одређене одлуке донесене. Упркос томе, отворени су за додавање могућности за генеричко програмирање у будућности, као и по питању побољшања у областима генерације кода и смањења трајања паузе приликом аутоматског ослобађања меморије.
Синтакса
Синтакса је најсличнија језицима из C породице језика, али је знатно измењена како би програми били концизнији и читљивији, као и да би подржала нове додатке језику.
Гоу уводи комбиновани оператор := за декларацију и иницијализацију променљивих. Уз помоћ овог оператора могуће је написати скраћен облик декларације и иницијализације који не захтева прецизирање типа података, већ то ради сам компилатор. Ово је супротно од декларације и иницијализације у C-у, где је обавезно увек навести тип променљиве. Постоји и проширена синтакса за декларацију и иницијализацију променљивих, али се она ређе јер је скраћени облик лакши за читање; често се користи само проширена декларација, када је потребно само резервисати име, а компајлер ће сам доделити нулту вредност (нпр. var broj int има вредност 0). Оператор = се користи за додељивање нове вредности променљивој која је већ декларисана.
// Гоу (скраћено) i := 3 s := "tekst" n := float64{1.0, 2.0, 3.0} // Гоу (продужено) var i int = 3 var s string = "tekst" var n float64 = float64{1.0, 2.0, 3.0} // C int i = 3; const char * s = "tekst"; double n = {1.0, 2.0, 3.0};
Искази се завршавају са симболом тачка-зарез, али се он не мора наћи у изворном коду на местима где се завршава ред. Алат go fmt из основне дистрибуције избацује овај симбол са места на којима је сувишан.
Функције могу враћати више вредности, па је шаблон враћања пара result, error главни метод индикације постојања грешке настале током позива дате функције. Сличан шаблон се примењује за приступ мапама и за локално проверавање типа податка, са тим што је тада пар који се враћа result, bool, где други параметар указује на тачност операције.
Гоу такође додаје синтаксу за иницијализацију параметара у struct типу по имену, као и за иницијализацију мапа и низова.
Као замену за C-ове for, while и do/while петље, Гоу уводи комбиновану for петљу која заједно са range изразом омогућује једноставну итерацију низова, одсечака, мапа, канала, и ниски.
Типови података
Основни типови података, који су уграђени у језик, су у првом реду нумерички типови. Ту спада и Булов тип података као и цели бројеви int, int8 (byte), int16, int32 (rune), int64, неозначени цели бројеви: uint, uint8, uint16, uint32, uint64, uintptr, бројеви у облику са покретним зарезом float32, float64 и комплексни бројеви complex64, complex128. Такође и ниске (string) спадају у уграђене типове. Ниске су непроменљиве, а помоћу уграђених оператора и кључних речи могуће је спајање, поређење и кодирање из и у UTF-8.Роб Пајк, Strings, bytes, runes and characters in Go, 23. октобар 2013
Слогови () се могу дефинисати уз помоћ кључне речи struct.
Типом податка T и бројем елемената n се дефинише низ означен са [n]T; пошто је број елемената део типа податка, низови којима су типови елемената исти али им је број елемената различит, су различитог типа.
Динамички низови се зову одсечци (); за тип податка T, одсечак који садржи вредности тог типа се означава са []T. Ови низови имају дужину и капацитет којим се означава када треба заузети нови део меморије за проширење одсечка. Неколико одсечака може да дели одређени меморијски простор.Ендру Џиренд, Go Slices: usage and internalsГоу Аутори, Effective Go: Slices
За пар типова података K, V, тип map[K]V означава тип мапе (хеш табела) која мапира кључеве типа K на вредности типа V. Хеш табеле су уграђене у језик, имају посебну синтаксу, и над њима се операције врше уграђеним функцијама.
Канали () служе за комуникацију између конкурентских процеса и такође имају своју синтаксу. За тип податка T, тип канала се означава са chan T. Језик поседује и скуп уграђених операција којима се вредности могу примати и слати преко канала.
Показивачи постоје за све типове података; за тип податка T, показивач се означава са *T. За разлику од C-а, нема показивачке аритметике, осим кроз тип Pointer из пакета unsafe у стандардној библиотеци.
Поред подршке за интерфејсе, систем типова је номиналан, односно заснива се на експлицитном именовању типова података. Кључна реч type ствара нови тип податка, који представља нови тип (а не алијас као у C-у) и који се разликује од осталих типова података који могу имати исти распоред у меморији (а у случају struct типа, и исти редослед поља). Неке конверзије између типова су уграђене, а додавањем новог типа се могу дефинисати додатне конверзије. Конверзије између типова су увек експлицитне; примера ради, сабирање два броја од којих је један а други захтева да један од два броја буде преведен у тип другог броја.
На пример, помоћу кључне речи type се може дефинисати тип за IPv4 адресе, које су 32-битни цели бројеви без предзнака:
type ipv4addr uint32
Са овом дефиницијом типа ipv4addr(x) интерпретира uint32 вредност у ИП адресу. Просто додељивање вредности x променљивој чији је тип ipv4addr није могуће јер, иако имају исту структуру у меморији, нису исти типови.
Константни изрази могу имати или немати типове; ако немају тип податка, он им се додељује када се њихова вредност додели некој променљивој, под условом да је конверзија могућа током компилације.
Функције такође имају типове. Могу да прихватају ниједан или више аргумената и да врате ниједну или више вредности; све ове вредности имају своје типове, а заједно они одређују потпис, односно тип функције. На пример, func(string, int32) (bool, error) је тип функције која као аргументе прима текст и 32-битни број са предзнаком (редом, string и int32), а враћа бул и грешку (редом, bool и error).
Сваки именовани тип може имати сет метода који је са њим повезан. Претходни пример се може проширити тако да има методе којим се врши штампање у читљивом формату, проверава да ли се налази у одређеном опсегу и слично, зависно од функционалности коју тип треба да има. Типу се метода додаје тако што се између кључне речи func и имена функције дода прималац (), који се састоји од имена које представља референцу (слично речима this и self у језицима као што су Јава и Пајтон) и типа на који се метода односи.
// Is this the zero broadcast address 255.255.255.255? func (addr ipv4addr) ZeroBroadcast() bool { return addr == 0xFFFFFFFF }
Због номиналног система типова, ова метода је додата типу ipv4addr, али не и типу uint32.
Иако за њихово дефинисање и позивање постоји посебна синтакса, методе немају засебан тип. Сама синтакса је заправо "синтаксни шећер" (), па ако је x променљива којој је додељена вредност чији је тип горепоменути ipv4addr, следеће две линије имају исто значење:
x.ZeroBroadcast() ZeroBroadcast(x)
Интерфејси
Гоу поседује две особине којима замењује систем наслеђивања из класичног објектно-оријентисаног програмирања. Прво је уграђивање, које представља форму композиције или делегације. Други део су интерфејси, који омогућују полиморфизам у току извршавања програма.
Интерфејси омогућују ограничен облик структурних типова података у оквиру номиналног система типова података. Сваки тип података над којим су дефинисане све методе из интерфејса имплицитно задовољава тај интерфејс. Сам систем интерфејса заснован је на систему протокола из језика Smalltalk. Интерфејс групише типове података у скуп, тако што сам представља листу метода које ти типови морају садрже. Типови који задовољавају одређени интерфејс не морају експлицитно то да нагласе, већ се та провера врши током компилације програма.
Типови Kvadrat и Krug се могу груписати помоћу интерфејса Oblik који од својих типова захтева да садрже методе Obim и Povrsina.
import "math"
type Oblik interface { Obim() float64 Povrsina() float64 }
type Kvadrat struct { stranica float64 } func (kv Kvadrat) Obim() float64 { return 4 * kv.stranica } func (kv Kvadrat) Povrsina() float64 { return kv.stranica * kv.stranica }
type Krug struct { poluprecnik float64 } func (k Krug) Obim() float64 {