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