UMEÅ UNIVERSITET
Institutionen för datavetenskap
26 februari 2015
Seminarierapport
Programspråk 7.5p
Google Go
Namn:
E-mail:
Jonas Hedin
[email protected]
Mattias Scherer
[email protected]
Namn:
E-mail:
Max Bågling
[email protected]
Mikael Karlsson
[email protected]
Namn:
E-mail:
Erik Berggren
Albin Råstander
[email protected] [email protected]
Handledare
Thomas Johansson
Google Go
Innehåll
Innehåll
1 Bakgrund och historik
1.1 Historik . . . . . . .
1.2 Syfte . . . . . . . . .
1.3 Arv . . . . . . . . .
1.4 Sammanfattning . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1
1
1
2
2
2 Uppbyggnad
2.1 Syntax . . . . . . . . . . .
2.2 Data . . . . . . . . . . . .
2.3 Concurrency . . . . . . . .
2.4 Konventioner . . . . . . .
2.5 Kontrollstrukturer . . . .
2.6 Hello world exempel i Go
2.7 Lite större exempel . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
2
2
2
3
3
3
3
4
språket passar till
Simpelhet och kompilering . . . . . . . . . . . . . . . . . . . . . .
Multi-processing . . . . . . . . . . . . . . . . . . . . . . . . . . .
Användning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4
5
5
6
3 Vad
3.1
3.2
3.3
.
.
.
.
.
.
.
.
4 Utvärdering
4.1 Utvecklingshastighet . .
4.2 Prestanda . . . . . . . .
4.3 Pålitlighet och säkerhet
4.4 Portabilitet . . . . . . .
4.5 Återanvändingsbarhet .
.
.
.
.
.
6
6
6
6
6
7
5 Inverkan
5.1 Läsbarhet och skrivbarhet . . . . . . . . . . . . . . . . . . . . . .
5.2 Inbyggda datatyper . . . . . . . . . . . . . . . . . . . . . . . . . .
7
7
8
6 Övriga källor
9
Seminarierapport
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
i
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
26 februari 2015
Google Go
1
1
Bakgrund och historik
Bakgrund och historik
1.1
Historik
21 september 2007 började Robert Griesemer, Rob Pike och Ken Thompson
skissa sina mål för ett nytt programmeringspråk på en whiteboard[1]. Inom ett
par dagar hade dessa mål lett vidare till en plan och en idé hur språket skulle se
ut. Designarbetet fortsatte parallellt med andra uppgifter som ett deltidsarbete
och i januari 2008 började Ken arbeta på en kompilator för att fortsätta utforska
ideer. Kompilatorn producerade då C-kod som sin output och fortsatte så ända
tills februari 2014 då man då övergick till en kompilator som producerar Go-kod.
Vid mitten av 2008 hade språket växt till ett heltidsarbete och Ian Taylor och
Russ Cox hjälpe till att förflytta språket och dess bibliotek från prototyp till
verklighet. I november 2009 blev projektet open source och många personer från
communityn har bidragit med idéer, diskussion och kod.
1.2
Syfte
Go skapades ur frustrationen med de existerande språken och utvecklingsmiljöerna. Programmering hade blivit för svårt, och valet av språk var en del av
problemet. Du var tvungen att välja på effektiv kompilering, effektiv körning
eller om språket var lätt att programmera i. Enligt utvecklarna gick det inte att
få alla tre i samma språk. Programmerare som valde lätthet över säkerhet gick
till språk såsom Python och Javascript istället för för C++ och Java.
Inget nytt stort språk har kommit de senaste tio åren trots att kraven och syften
med programmering har ändrats oerhört. Nedan har vi några av de problem som
Go försöker lösa.
• Datorers hastighet har ökat markant men mjukvaru-utvecklingens hastighet står still.
• Att hantera beroenden är en stor del av utvecklingen idag men såsom
andra språk är uppbyggda så blir kompileringen inte effektiv.
• Det har växt ett stort motstånd mot klumpiga datatyper som i C och
Java, man vill hellre ha dynamiskt typade variabler som i Python och
Javascript.
• Vissa koncept såsom garbage collection och parallella beräkningar är inte
så välimplementerade i existerande språk.
Go försöker kombinera enkelheten att programmera med ett interpreterat och
dynamiskt typat språk med effektiviteten och säkerheten med ett statiskt typat
och kompilerat språk. Det siktar även på att vara ett modernt språk med support
för flertrådade program samt support för nätverksprogrammering. Slutligen ska
det även vara snabbt, det ska inte ta mer än ett par sekunder att kompilera
ett stort program. För att klara alla dessa krav så krävdes ett nytt språk, det
räcker inte med att använda existerande bibliotek och verktyg.
Seminarierapport
1
26 februari 2015
Google Go
1.3
2
Uppbyggnad
Arv
Go ärver först och främst från C-familjen av programmeringsspråk (syntax),
men har stora influenser av Pascal/Modula/Oberon-familjen (deklarationer,paket),
och tar även lite idéer från språk som Newsqueak och Limbo (concurrency). Det
är dock ett helt nytt språk, alla delar i språket är designade efter hur en programmerare programmerar.
1.4
Sammanfattning
Go utvecklades först för att lösa problem som uppstått i och med konstruktion
av mjukvara till stora servrar. Det kanske låter som att Go bara används inom
industrin men eftersom fokuset ligger vid enkelhet och tydlighet så kan Go vara
ett språk som kan ses som kraftfullt och uttrycksfullt av många programmerare.
2
Uppbyggnad
Go liknar C men har många ändringar med mål att göra koden koncis, lättläst
och säker. För att göra Go lätt har man inte: typarv, metod- eller operatoröverladdning, cirkulär beroenden bland paket, pekararitmetik, assertions (predikat)
eller generisk programmering[2].
2.1
Syntax
Go förkortar C genom att deklarera en variabel i := 3 eller s := "Hello
world" istället för säga att variabeln är av typen int eller string. Dock om
man vill deklarera en variabel utan att initiera ett värde kan man skriva var
i int där man definerar vilken datatyp variabeln är. Funktioner deklareras
som t.ex. func Namn(a int, b string) (n int, err error) där första parantesen innehåller inparametrar och den andra är returvärden. Notera att man
skriver variabelnamnet först och sen typen. Go använder semikolon som C fast
de förekommer inte i källkoden utan det är lexical analyzer som automatisk sätter semikolon när den skannar genom att följa några regler. Men semikolon kan
användas i for statement för att separera initialisering, tillstånd, och fortsättningselementet. En konsekvens av insättningsreglerna för semikolon så kan man
inte börja med en måsvinge på ny rad för control statements (t ex. if, for, switch,
eller select). Funktioner kan returnera flera värden. Ett konventionellt sätt är
att returnera ett result, err par från en funktion så kan ett error indikeras till
sin kallare. defer är ett statement som schemalägger en funktionskallelse som
körs innan funktionen returnerar. Defer är bra att använda om man vill släppa
en resurs oavsett vilken väg funktionen tar till return statement, t.ex. stänga en
fil.
2.2
Data
new är en inbyggd metod i Go för att allokera minne och nolla det. new(T)
allokerar ett nollat utrymme för en typ T och returnerar adressen. make är
Seminarierapport
2
26 februari 2015
Google Go
2
Uppbyggnad
en annan inbyggd funktion som initierar en datastruktur i minnet som inte
är nollat. Slices är en datatyp som har en pekare till en array i minnet, samt
innehåller den längd och kapacitet för minnesutrymmet.
2.3
Concurrency
Go erbjuder möjlighet för att skriva trådade program som delar tillstånd genom
kommunikation. För att skriva trådade program i Go görs det endast med ett
simpelt go-statement. go func() startar en s.k. goroutine som är en lightweightprocess. För att göra programmet synkroniserat finns det Channel types. chan
type ger en typsäker, synkroniserad, buffrad kanal mellan goroutines. Med kanaler kan man skicka värden med ch <- x statement som skickar x över ch.
För att ta emot från kanalen har man <- ch statement. Båda operationerna
blockerar tills kanalen är redo för kommunikation.
2.4
Konventioner
Synligheten för ett namn utanför ett paket bestäms av om första bokstaven
är versal, det vill säga stor eller liten bokstav. Namn med flera ord skrivs helst
som Mixedcaps eller mixedCaps istället för underscores. Namn på Interface med
bara en metod har samma namn som metoden plus en -er suffix, tex Reader,
Writer, Formatter. Getters skrivs inte med Get i getterns namn.
2.5
Kontrollstrukturer
Det finns ingen do eller while loop i Go, istället använder man for. För if
och switch statements finns det möjlighet att initialisera som man kan i forstatements. break och continue tar en valfri label som man kan avbryta till.
En switch kan användas dynamisk för en interface variable genom att skriva
var.(type). Uttrycken i en switch behöver inte vara konstanter vilket betyder
att en if-else kedja kan göras i switch. select är en flervägs kommunikations
multiplexer som fungerar ungefär som switch fast för kanaler. Control statements har inga paranteser och kroppen ska alltid vara inom måsvingar[3].
2.6
Hello world exempel i Go
package main
import "fmt"
func main() {
fmt.Println("Hello, World")
}
Seminarierapport
3
26 februari 2015
Google Go
2.7
3
Vad språket passar till
Lite större exempel
Det här programmet löser en uppgift på https://open.kattis.com/problems/
bookingaroom. Programmet tar input från stdin och med en algoritm tar den
reda på lediga rum på ett hotel. Om ett ledigt rum finns skrivs rumsnummret
ut annars blir output too late.
// bookingaroom
package main
import (
"fmt"
"sort"
)
func main() {
var r, n int
fmt.Scan(&r)
fmt.Scan(&n)
var list = make([]int, n)
for i := 0; i < n; i++ {
fmt.Scan(&list[i])
}
sort.Ints(list)
for i := 1; i <= r; i++ {
if i > r {
break
} else if i > n {
fmt.Println(i)
return
} else if list[i-1] != i {
fmt.Println(i)
return
}
}
fmt.Println("too late")
}
3
Vad språket passar till
Google Go är delvis ett objektorienterat språk, men samtidigt inte. Då Go saknar hierarki är det tänkt att objekten ska kännas mycket lättare än i språk som
C++ och Java. Då Go skapades för att bygga upp Googles system så går det
att dela upp språkets användbarhet i de viktigaste faktorerna enligt skaparna
själv, vilket är dess simpelhet, kompilering samt hur den hanterar samtidighet
(concurrency).
Seminarierapport
4
26 februari 2015
Google Go
3.1
3
Vad språket passar till
Simpelhet och kompilering
Google Go passar bra till utvecklare som gillar att programmera i ett språk som
är elegant och simplistiskt. Tack vare garbage collection som sker automatiskt
i språket så ger det användaren mer tid att tänka på annat. En viktig tanke
från utvecklarna av språket är att det på senaste decenniumet har blivit en
trend att göra datorerna snabbare men inget har gjorts för att göra mjukvaruutvecklingen snabbare, Go skapades för med syfte att vara ett språk som är
lättare och snabbare att programmera i än språken som finns ute på marknaden
idag.
Go är ett bra språk att lära sig programmera i, då det finns lite saker att hålla
reda på till en början. Så som att man inte behöver definera att en variabel är en
int eller string, m.m, vilket måste göras i de flesta andra språk. Ett exempel är
om man skriver följande ( a, b := "Hej", 3) så sätter man en variabel a till
en string och en variabel b till en int, utan att säga att specifikt säga att a ska
vara en string och b en int. Språket kan även returnera flera möjliga variabler,
vilket kan vara väldigt intuitivt för nybörjare, då det är lättare att förstå än
att man ska bygga upp en lista som klarar av att ta olika typer och returnera
denna, vilket kan krävas i andra språk.
Skaparna av Google Go säger att de bestämde sig för att använda små och stora
bokstäver i början av en identifierare, för att säga om identifieraren är privat
eller publik[7]. Detta medför att det är väldigt lätt att se på en identifierare och
säga direkt om det tillhör ett publikt API. Detta är en del av språkets simpelhet,
och att det ska gå lätt att se vad som händer. Användare av Go säger att efter de
använt detta så är det jobbigt att gå tillbaka till andra språk som inte använder
sig av detta.
En stor anledning till att Google Go skapades var att det tog runt 40 minuter
att kompilera deras största system i C++, och de ville att kompileringen skulle
ta mindre tid, med Go tar det bara några minuter för samma kompilering. Go
passar därför som sagt företag och projekt som har stora program som måste
kompileras om ofta, då det ska gå att kompilera dessa program på bara några
sekunder på en enstaka dator. En av många orsaker till att det kompileras
snabbt är att det ser efter om det importerar ett paket som inte används, och
returnerar då ett error istället för att bara ge en varning och läsa in onödig kod.
3.2
Multi-processing
Google Go har features för multitrådade program exempelvis såkallade goroutines
och channels. Idén för goroutines är att låta oberoende funktioner exekvera på
ett antal trådar och när en funktion blockerar en tråd så kommer Go automatiskt under körningen flytta övriga oberoende funktioner till fria ej blockerade
trådar. Go fixar även rutinernas storlek till skillnad ifrån vanliga trådar vilket
resulterar i att ett program i go kan ha många fler rutiner än vad c kan ha
trådar. För att kommunicera mellan rutiner används channels vilket påminner
om pipes i C/C++. Skillnaden är att channels blockerar tills skrivare och läsare
är redo för informationen utan att mer synkronisering behövs. Detta lämpar Go
till applikationer då extremt många trådar behövs såsom servrar.
Tack vare denna smidiga multi-processing i Go så används språket flitigt i blandannat webbapplikationer som måste fungera med ett stort antal klienter, ett
Seminarierapport
5
26 februari 2015
Google Go
4
Utvärdering
exempel på detta är t.ex en Go-applikation som gör att någon miljon användare
kan komma åt och spela upp ett klipp på youtube samtidigt[8].
3.3
Användning
Google go är ett språk anpassat för systemprogrammering. kompilerade program
får i regel inte lika hög prestanda som C/C++ men det är enklare att hantera
minnen och trådar. Det finns stöd för direkt minnesåtkomst samt att skriva
direkta assembler kommandon vilket kan vara extremt användbart vid systemprogrammering. Go är ett levande språk och det finns ett stort antal tredjeparts
bibliotek som utökar språkets användningsområden. I stort sett kan Go användas
på samma områden som C men är lättare att skriva kod snabbt i.
4
4.1
Utvärdering
Utvecklingshastighet
Eftersom Go har ett stort standardbibliotek och det är enkelt att få tag i tredjepartsbibliotek så bör utvecklingstiden för applikationer vara relativ låg för
programmerare med vana för språket.
4.2
Prestanda
Go är i regel långsammare på att exekvera kod än exempelvis C/C++ tack vare
bland annat garbage collectors. Samt har Go i regel mycket större kompilerade
filer. Så i system med begränsade resurser kan andra språk med fördel väljas.
4.3
Pålitlighet och säkerhet
Go har en design som påminner om C men är säkrare med hjälp av garbage collectors och typkontroll. Det finns för närvarande kritik mot att språkets inbyggda
features för trådäkerhet kan skapa såkallade dead-locks i väldigt sällsynta fall.
Googles svar på kritiken är att man borde programmera på ett annat sätt i Go
jämfört med andra språk för att undvika dead-locks. Detta är bland annat
på grund av att alla atomiska operationer är inte definerade än. Mutex-lås existerar men Google hoppas på att programmerare kommer använda Go på ett
sådant sätt så att inte behöver dessa. “Do not communicate by sharing memory.
Instead, share memory by communicating.”
4.4
Portabilitet
GO’s kompilator har targets till Linux, Mac OS X, FReeBSD, NetBSD, OpenBSD,
Plan 9 och Windows, implementerat för i386, amd64, ARM och IBM POWER
arkitektuerna. Detta gör att det är relativt enkelt att korskompilera program
till dessa system. En av de högsta prioriteterna för språket är att kompabilitiet
ska bli ännu bättre.
Seminarierapport
6
26 februari 2015
Google Go
4.5
5
Inverkan
Återanvändingsbarhet
Det är extremt enkelt att skapa egna paket och återanvända. Go stödjer att
man kan ladda ner paket direkt från exempelvis git. Vilket möjligör att dela sin
egen kod med andra utvecklare. Det är även detta som medför att det är lätt
att använda tredjeparts bibliotek.
5
Inverkan
5.1
Läsbarhet och skrivbarhet
Syntaxen i Go baseras till stor del på C, där de flesta skillnader försvårar läsningen av koden och förenklar skrivandet av koden. Några exempel på detta kan
vara att man kan välja att inte typdeklarera sina variabler, deklarera olika typer
av variabler med nyckelordet var eller skapa olika sorters listor med nyckelordet
make. Förutom enkelheten att deklarera variabler i Go så har man dessutom
infört garbage collection vilket gör det lättare för utvecklaren att lyckas skriva
ett program, men försämrar prestandan.
Operator overloading
I Go finns inget som heter operator overloading, vilket innnebär att man inte
kan säga att till exempel plus-tecknet ska innebära konkatenering av strängar.
Detta kan sägas ha en negativ effekt på både läsbarhet samt skrivbarhet. Jämför
till exempel hur intuitivt strängkonkatenering ser ut i Java (som visserligen inte
har operator overloading förutom i specialfallet strängar) i jämförelse med
C (som helt saknar saknar operator overloading)[4].
I Java:
string1 += string2;
I C:
strcat(string1, string2);
I fallet skrivbarhet är avsaknaden av operator overloading negativ i det
avseendet att programmeraren inte kan förenkla ofta använda funktionsanrop/rutiner. Det ger även mindre/ingen kontroll över beteendet av operatorer.
Interfaces
Det finns ingen typ av arv i Go, språket förlitar sig istället helt och hållet på
interfaces. Designvalet medför en försvårad läslighet men samtidigt en förbättrad ortoganalitet gällande skrivbarhet. Ska ytterligare funktionalitet läggas till
kan detta göras genom ett ytterligare interface istället för att ändra i de klasser som befinner sig högre upp i hierarkin. Go möjliggör dock implementering av
flera interfaces vilket kan försvåra läsligheten. Vidare sker implementeringen
av interfaces inte på ett lika tydligt sätt som i till exempel Java[5].
Undantag
Seminarierapport
7
26 februari 2015
Google Go
5
Inverkan
Det vanligaste sättet att generera ett undantag i Go är att låta en funktion
returnera ett extra returvärde, lämpligtvis av typen os.Error. Efter funktionsanropet kontrolleras det om det faktiskt returnerades ett Error-objekt, om så
är fallet sker en lämplig åtgärd[6]. Här följer ett exempel:
f, err := os.Open("filename.ext")
if err != nil {
log.Fatal(err)
}
Assertions
Till skillnad från till exempel Java finns inget assert-keyword eftersom att
utvecklarna bakom språket anser att fall som kräver något sådant aldrig ska
behöva uppstå.
Pekararitmetik
Något som förenklar för läsaren är avsaknaden av pekararitmetik, vilket medför
att man aldrig kommer att behöva fundera över vad som händer t.ex när pekaren
utsätts för en högerskiftning och adderas med fem.
Generiska typer
För tillfället så saknar Go generiska typer (det kanske kommer att implementeras[7])
vilket löses med att använda generella inbyggda typer för att gå runt detta. Det
leder till att koden blir mer svårläst och att programmera en lösning blir svårare
då det görs mer osmidigt än om generics var inbyggt i språket.
Cirkulära beroenden
Paketen i Go får inte innehålla cirkulära beroenden, det blir en extra sak att
tänka på när programmet skrivs men förenklar i längden då konstiga fel p.g.a.
detta kan undvikas.
5.2
Inbyggda datatyper
Slice Är ett segment av en array. Såsom en array så är en Slice indexerbar och
har en längd. Till skillnad från en array så kan längden ändras.
Channel Skapar ett sätt för två rutiner att kommunicera med varandra och
synka sina körningar.
Seminarierapport
8
26 februari 2015
Google Go
6
Övriga källor
Referenser
[1] http://golang.org/doc/faq#history
[2] http://en.wikipedia.org/wiki/Go_\%28programming_language\%29
[3] https://golang.org/doc/effective_go.html
[4] http://golang.org/doc/faq#types
[5] https://golang.org/doc/effective_go.html#interfaces_and_types
[6] http://www.golangpatterns.info/error-handling
[7] http://golang.org/doc/faq#generics
[8] http://athega.se/blogg/2014/09/26/GO-kommer-revolutionera-webben
6
Övriga källor
http://talks.golang.org/2012/splash.article
http://golang.org/doc/
http://golang.org/doc/faq
http://www.golang-book.com/
http://en.wikipedia.org/wiki/Go_(programming_language)
http://peter.bourgon.org/go-in-production/
http://www.lessonsoffailure.com/software/google-go-good-for-nothing/
Seminarierapport
9
26 februari 2015