Programmeren in Go: verschil tussen versies

Verwijderde inhoud Toegevoegde inhoud
Danielheres (overleg | bijdragen)
Bijna klaar
Zo goed als klaar
Label: Herhaalde karakters
Regel 1:
Zo goed als klaar! Hulp gewenst bij formatting pagina.
Bijna klaar! Suggesties welkom op overlegpagina!
PDF : http://commons.wikimedia.org/wiki/File:Een_introductie_in_Go_(1).pdf
 
Auteur: Daniël Heres
 
Go: een snelle introductie
 
Auteur: Daniël Heres
Datum: Januari 2010
 
 
'''3,2,1 Go!'''
 
"Weer een nieuwe taal!" zul je wel denken. De keuze in programmeertalen is groot en de gelijkenis vaak ook. Toch is er een ding dat vaak overeind blijft: het gebruik van talen met statische types (system language). Deze talen zijn vaak een stuk sneller omdat er bijvoorbeeld met 32-bits typen gerekend kan worden terwijl bij de meeste dynamische talen er met 64-bit floats gerekend wordt of omdat een array uit één type kan bestaan. Een ander groot verschil tussenkun dynamischeje envinden statische talen is vaakin de complexiteit van een taal: talen als C++ kunnen heel complex worden met hun klassensysteem. Daardoor kunnen eenvoudigere talen (vooral wanneer het aantal bestanden toeneemt) veel sneller gecompileerd worden. Dat blijkt vooral handig handig bij het ontwikkelen van programma's en bij JIT-(Just In Time) compileren. Go is een taal die niet echt als doel heeft een nieuwe syntax door te voeren (zoals veel nieuwe dynamische talen) maar de snelheid van talen met statische types te combineren met het gemak van dynamische talen en een supersnelle compilatie. DezeOoit taalbegonnen wordtals ontwikkeld20%-project doorvan een paar Google engineers ontwikkelt Google de taal door. De drijfveer van Google is duidelijk: enerzijds webapplicaties maken met veel meer mogelijkheden die op elk platform kunnen draaien en daarnaast snel afgeleverd worden en anderzijds sneller ontwikkelen van grote complexe systemen door snelle compilatie. Go maakt een goede indruk als een alternatief voor bestaande system languages en JavaScript.
 
Deze gids is gemaakt voor mensen die al wat programmeerervaring hebben en snel basisconcepten van deze nieuwe taal willen leren.
 
'''Commentaar'''
 
Commentaar is hetzelfde als veel andere talen.
<pre>
 
/* Dit is commentaar
over meerdere
regels */
// Commentaar voor één regel
</pre>
 
'''Pakketten'''
 
Pakketten
 
De eerste regel van Go moet een pakketnaam beschrijven. In een Go project moet er minstens één pakket zijn met de naam main en die moet een functie met de naam "main" bevatten.
 
<pre>
package kabouters // Andere pakketten in project kunnen dit kabouterpakket importeren
 
Regel 34 ⟶ 33:
 
import "./mutsen" // Pakket beschikbaar in map
</pre>
 
'''Variabelen en constanten'''
 
Het declareren van variabelen en typen gaat in Go behoorlijk anders dan in de meeste talen. Typen worden achteraf gedeclareerd, na de namen. Dit is duidelijk te zien in het volgende voorbeeld.
 
<pre>
var a int // Variabele a heeft type int. Let op: een puntkomma als einde voor een statement is voor Go niet noodzakelijk (mag wel)
 
Regel 45 ⟶ 46:
const r int = 5 // e is een constante
 
var f = 5 // DitType kanint. bij numerieke types, typesTypes worden automatisch toegewezen aan getallen en strings
 
var g string = "Go go go!"
Regel 54 ⟶ 55:
j int32 = 45;
k, l, m = "GOOG", 43, 1.0
) // Gebruik van haakjes is heel handig bij declareren van veel variabelen, puntkomma's zijn verplicht als scheidingsteken! Haakjes kunnen ook bij sleutelwoorden const en type gebruikt worden.
 
const (
Regel 69 ⟶ 70:
p, q, r := 5.7, 100, "Kort"
}
</pre>
 
 
 
Regel 75 ⟶ 76:
De laatste constanten kunnen bijvoorbeeld door een programma verkleind worden tot
 
<pre>
const(a,b,c,d,e,f=9,7,10,8,5,2)
</pre>
 
 
Dat is natuurlijk geen toeval. Grote programma's moeten zo snel mogelijk over een netwerk verstuurd worden, daar helpt een korte notatie natuurlijk goed bij! Hier zal ook bij de volgende concepten goed over nagedacht zijn!
Regel 82 ⟶ 84:
Tot slot, de numerieke types zijn:
 
int uint float
int8 uint8 of byte
int16 uint16
int32 uint32 float32
int64 uint64 float64
 
 
 
'''Assignments'''
 
Laten we meteen maar met een paar voorbeelden beginnen!
 
<pre>
a = x
 
b, c = functie1(), 5 // Meerdere assignments, we zien inop hetde volgende regel waar dat heel handig voor is
 
d, e = e, d // Wisselen van variabelen! Hiervoor zijn bij minder expressieve talen drie regels voor nodig
 
</pre>
 
If
 
Voor eeneenvoudige if-statementstatements worden geen haakjes gebruikt. DeDaarnaast restmoet iseen gelijkelse aanif deof meesteelse die bij een vorige if hoort op dezelfde regel staan als de anderesluitende talenaccolade.
 
<pre>
import "fmt" // importeert pakket fmt
 
func main() {
if x<a {
klein()
} else if x>a { // Let op, else en else if moeten op zelfde regel als sluitende accolade!
groot()
Regel 121 ⟶ 126:
}
 
</pre>
 
 
 
 
Operators
Voorrang
 
6 / % << >> & &^
56 + -/ % << >> |& &^
45 == != <+ <=- >| >=^
4 == != < <= > >=
3 <- (Deze operator wordt gebruikt voor communicatie tussen Goroutines)
3 <- (Deze operator wordt gebruikt voor communicatie tussen Goroutines)
2 &&
2 &&
1 ||
1 ||
 
 
For
'''For'''
 
Een for loop gebruikt ook geen haakjes. Een for loop heeft twee verschillende modussen: één met één element en één met drie elementen.
 
<pre>
for a<5 {} // Dit is gelijk aan een while statement in andere talen
 
Regel 144 ⟶ 152:
for a:=0; ; a++{} // while(true) en een counter!
 
for a:=0; a<10; a++ {} // Een gewone for-looptloop
 
for i := range x {} // Probeer deze iterator op verschillende types! Let op: werkt niet voor integers zoals bijvoorbeeld bij programmeertaal Python.
</pre>
 
 
'''Switch'''
 
Switch
 
Switches zijn grotendeels gelijk aan andere talen met een paar belangrijke verschillen: alle types kunnen gebruikt worden en er is geen break nodig (waarmee vaak fouten worden gemaakt), het switch statement stopt standaard zodra er een kloppende voorwaarde is.
 
<pre>
switch f(10){
case 100: Print("Vertienvoudigd!")
Regel 162 ⟶ 171:
 
switch f:=f(10);{ // Je kan ook meerdere variabelen of declareren!
case f>100: Print("Erg groot");// Expressies in een switch statement
case f>10: Print("Aardig groot") fallthrough; // Gaat door naar volgende case, ook als hij waar is
case f==20: Print("Aardig groot en ook nog 20!")
}
</pre>
 
'''Functies'''
 
Functies
 
Kenmerkend voor Go zijn de notatie van parameters en de mogelijkheid om meerdere waardes te "returnen". Een functie wordt gedeclareerd met "func".
<pre>
 
/* Meerdere waardes kunnen voor het registreren van fouten gebruikt worden
*/
Regel 179 ⟶ 188:
}
 
func Konijn(wortels int) (genoeg bool) { // Als je parameters benoemt kun je ze gebruiken
if wortels > 10 { genoeg = true; }
return genoeg
 
}
 
 
func Konijn(wortels int) (genoeg bool) {
if wortels > 10 { genoeg = true; }
return // genoeg wordt "gereturned", kleiner dan tienelf -> false
}
 
func FunctieInFunctie(i int) (int) (
g := func(j int) (int) { // Bij aanroepen functie Konijn function call Konijn() in body zetten
h := j * i + 1;
return h
Regel 200 ⟶ 211:
x = x +5
}
</pre>
 
'''Defer'''
 
Defer
 
Defer is een statement die als functie heeft om de executie van een statement te verplaatsen naar het einde van een functie. De volgorde van executie is LIFO, het laatste statement wordt als eerste uitgevoerd. Dit kan handig zijn om meerdere functies te groeperen, bijvoorbeeld bij IO.
 
<pre>
func main(element InfoElement)(Info) {
func o := openmain(element FileElement)(Info) {
o := file.Open(element)
defer o.Sluiten() // Verplaatst zich naar onderen
defer o.Close() // Verplaatst zich naar onderen
 
p := o.InfoReadAll() // Sluit is nog niet uitgevoerd!
// Nu pas!
return p
}
</pre>
 
'''Arrays'''
 
<pre>
var x = [4]int{2, 8, 19, 30} // Maak een array met lengte 4 en waardes 2, 8, 19 en 30
var y = [4]int{2, 9} // Array met lengte 4, met waardes 2, 9, 0, 0
Regel 230 ⟶ 244:
for i := range x {
fmt.Print(i) // 0, 1, 2, 3
fmt.Print("\n")
}
 
for _, j := range x { // Een array heeft keys (index) en waardes, indien je keys niet nodig hebt gebruik je een laag streepje om alleen de waardes op te vragen!
fmt.Print(j) // 2, 8, 19, 30
Regel 248 ⟶ 262:
 
}
</pre>
 
'''Slices'''
 
Slices zijn vrij uniek voor Go. Slices zijn eigenlijk verwijzingen naar arrays met een variabele lengte. Omdat slices verwijzingen zijn (alle instanties die aangemaakt zijn met functie "make()") hoef je niet met pointers te werken.
Slices
 
Slices zijn vrij uniek voor Go. Slices zijn eigenlijk verwijzingen naar arrays met een variabele lengte. Omdat slices verwijzingen zijn hoef je niet met pointers te werken.
 
<pre>
var a = []int{} // Integer slice
var b = []string{} // String slice
Regel 266 ⟶ 281:
return sl
}
</pre>
 
'''Methodes'''
Interfaces
 
InterfacesMethodes zijn in Go niks anders dan functies met een ontvanger. De ontvanger komt voor de naam van de functie.
 
<pre>
func (o *ObjectType) FunctieNaam() (aanroep int) returnwaarde int {
}
// Dus
func (v *Vector2D) Optellen() (w *Vector2D) {
v.x = v.x + w.x
v.y = v.y + w.y
}
</pre>
 
'''Types'''
We zien bij het onderwerp "types" hoe we interfaces in functies kunnen gebruiken.
 
 
Types
 
In Go kan je verschillende soorten types aanmaken. Types zijn niet hetzelfde als types in andere programmeertalen.
 
Soort type Eigenschap
Type van een al bestaand type Nieuwe naam voor type, mogelijk uitbreiden met methodes.
Interface Beschrijft interfacesmethodes. Wordt gebruikt om meerdere implementaties van een systeem mogelijk te maken.
Struct Vormt structuur van geheugen (velden en methoden). Lijkt een beetje op een klasse uit andere talen maar heeft niet precies dezelfde functie.
Je kan instanties van dit type aanmaken.
 
Type van een type
 
''Type van een type''
 
<pre>
type Dag int
type Kracht float
type Mensen []string
 
// Uitbreiden met methodes
Interface
 
func (d Dag) DagNaarJaar() int {
return d / 365 + 1
}
 
func (k Kracht) KrachtNaarGewichtAarde() float {
return k / 9.81
}
</pre>
 
''Interface''
 
<pre>
type Honden interface { // Specificatie interface
Rennen(h *Hond) // *Voer betekent verwijzing naar object met type Voer
Regel 305 ⟶ 334:
}
 
func (h *Hond) Rennen() { // InterfaceMethode, kan ook zonder specificatie
// *Hond is recievertype, kan voor elk type
h.ren = true
}
 
func (h *Hond) Eten(v Voer) bool { // Nog een interfacemethode
if (h.ren || v == PrutUitBlik) {
return false
Regel 316 ⟶ 345:
return true
}
</pre>
 
''Struct''
 
<pre>
Struct
 
type Hond struct {
x,y int
Regel 338 ⟶ 368:
fmt.Print(monty.Eten(Brokken)) // Wat wordt dit?
}
</pre>
 
'''Goroutines'''
 
Programmeurs vinden concurrency vaak lastig. Go heeft het uitvoeren van meerdere code in dezelfde geheugenruimte in de taal ingebouwd om het een stukje makkelijker te maken. Een Goroutine wordt gestart door het sleutelwoord "go".
Goroutines
 
Programmeurs vinden multithreading vaak lastig. Go heeft het uitvoeren van meerdere code in dezelfde geheugenruimte in de taal ingebouwd om het een stukje makkelijker te maken. Een Goroutine wordt gestart door het sleutelwoord "go".
 
<pre>
func zegHoi() {
fmt.Print("Hoi")
Regel 352 ⟶ 383:
time.Sleep(1000000000) // Nanoseconden
}
</pre>
 
 
We kunnen ook een anonieme functie gebruiken.
 
<pre>
func main() {
go func() {
Regel 362 ⟶ 395:
time.Sleep(1000000000)
}
</pre>
 
Buiten dat het geen zin heeft om een aparte Goroutine te openen om naar een console te schrijven is er iets anders: er is helemaal geen garantie dat de Goroutines wordenvolledig is uitgevoerd.
Daarvoor zijn Channels in het leven geroepen.
 
 
'''Channels'''
 
Channels worden gebruikt om te wachten en om informatie uit te wisselen, bijvoorbeeld over de status van een berekening.
 
<pre>
var quit = make(chan bool) // Maakt een channel met communicatietype bool
 
Regel 381 ⟶ 416:
fmt.Print(x) // Geeft output true in console
}
</pre>
 
 
We kunnen dat zo vaak als we willen communiceren met een Goroutine.
 
<pre>
var comm = make(chan int)
 
Regel 402 ⟶ 438:
}
}
</pre>
 
 
We kunnen meerdere Goroutines parallel uitvoeren. Om meerdere channels aan te maken gebruiken we
channelnaam := make(chan Type, aantal). De volgende code simuleert een hond met 4 koppen die elk 1 seconde nodig hebben om een brok op te eten.
 
<pre>
package main
 
import "fmt"
import "time"
 
const Cores = 4
Regel 415 ⟶ 457:
}
 
func EetBrok(h *Hond), Brok(c chan bool) {
time.Sleep(1000000000)
h.stuks = h.stuks - 1
fmt.Printf("Brok opgegeten, nog %d \n", h.stuks)
c<-true
}
 
func (h *Hond) EetBrokken(brokken int) {
if h.ren { // Als hond niet rent kan hond geen brok eten.
return
}
h.stuks = brokken
c := make(chan bool, Cores)
j := brokken / Cores
for k:=0; k<j; k++ { // We willen (brokken / Cores) keer met 4 koppen eten
for i:= 0; i<Cores; i++ { // We vullen 4 channels
go h.BrokEetBrok(h, c)
}
for i:= 0; i<Cores; i++ { // We wachten op de 4 channels
<-c
}
}
 
nogtedoen := h.stuks // Als aantal brokken niet te delen is door 4 moeten we nog een
nogtedoen := h.stuks // Als aantal brokken niet te delen is door 4 moeten we nog een aantal brokken eten
aantal brokken eten
if nogtedoen==0 {return}
for i:=0; i<nogtedoen; i++ {
go h.BrokEetBrok(h, c)
}
 
for i:= 0; i<nogtedoen; i++ {
<-c
}
}
 
func main(){
rex := &Hond{7, 9, truefalse, 0}
rex.EetBrokken(50)
}
</pre>
 
'''Select'''
 
Select is een statement dat op een vergelijkbare manier als switch gebruikt kan worden maar alleen voor communicatie van channels wordt gebruikt.
 
<pre>
package main
 
import "rand"
import "fmt"
import "time"
 
type Koe struct {
n int // Koeiennummer
gras int // De koe eet soms gras en soms niet.
}
 
func GrazendeKoe(n int, chan1 chan *Koe, chan2 chan *Koe) {
koe := &Koe{n, 0}
r := rand.New(rand.NewSource(time.Nanoseconds())) // Nanoseconds is een seed
var j int
for {
j = r.Intn(2) // Waarde tussen 0 en 1
koe.gras = j
if j==0 {
chan1 <- koe
} else {
chan2 <- koe
}
time.Sleep(1000000000)
}
}
func main() {
var k *Koe
chan1 := make(chan *Koe) // Koe loeit naar boer 1
chan2 := make(chan *Koe) // Koe loeit naar boer 2
go GrazendeKoe(1, chan1, chan2)
go GrazendeKoe(2, chan1, chan2)
for {
select {
case k = <- chan1: // Als we een signaal van chan1 krijgen
fmt.Printf("Koe %d, Boer 1, Gras: %d \n", k.n, k.gras)
case k = <- chan2: // Waarde niet opslaan kan door laag streepje
fmt.Printf("Koe %d, Boer 2, Gras: %d \n", k.n, k.gras)
}
}
}
</pre>
Informatie afkomstig van https://nl.wikibooks.org Wikibooks NL.
Wikibooks NL is onderdeel van de wikimediafoundation.