1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
|
---
name: Go
category: language
language: Go
filename: learngo.go
contributors:
- ["Sonia Keys", "https://github.com/soniakeys"]
translators:
- ["Szabó Krisztián", "https://github.com/thenonameguy/"]
---
A Go programozási nyelv az életszerű feladatok könnyebb elvégzése miatt született.
A mai legújabb programozási trendeket elkerülve,
praktikus megoldást nyújt a valós, üzleti problémákra.
C-szerű szintaktikával és statikus típuskezeléssel rendelkezik.
A fordító szempillantás alatt végez és egy gyorsan futó,statikus futtatható állományt hoz létre.
A nyelv könnyen érthető, üzenet-alapú konkurenciát tesz lehetővé, így könnyen ki lehet használni
a mai számítógépek több magos processzorait, ez nagy rendszerek építéséhez ideális.
A Go alap könyvtára mindenre területre kiterjed, ennek köszönhetően a nyelvnek egyre növekvő tábora van.
```Go
// Egy soros komment
/* Több
soros komment */
// Minden forrás fájl egy csomag-definícióval kezdődik, ez hasonlít a Python csomagkezelésére
// A main egy különleges csomagnév, ennek a fordítása futtatható állományt hoz létre egy könyvtár helyett.
package main
// Az import rész meghatározza melyik csomagokat kívánjuk használni ebben a forrásfájlban
import (
"fmt" // A Go alap könyvtárának része
"net/http" // Beépített webszerver!
"strconv" // Stringek átalakítására szolgáló csomag
)
// Funkció deklarás, a main nevű funkció a program kezdőpontja.
func main() {
// Println kiírja a beadott paramétereket a standard kimenetre.
// Ha más csomagot funkcióját akarjuk használni, akkor azt jelezni kell a csomag nevével
fmt.Println("Hello world!")
// Meghívunk egy másik funkciót ebből a csomagból
beyondHello()
}
// A függvények paraméterei zárójelek között vannak.
// Ha nincsenek paraméterek, akkor is kötelező a zárójel-pár.
func beyondHello() {
var x int // Változó deklaráció, használat előtt muszáj ezt megtenni.
x = 3 // Változó értékadás
// "Rövid" deklaráció is létezik, ez az érték alapján deklarálja, definiálja és értéket is ad a változónak
y := 4
sum, prod := learnMultiple(x, y) // a függvényeknek több visszatérési értéke is lehet
fmt.Println("sum:", sum, "prod:", prod) // egyszerű kiíratás
learnTypes()
}
// A funkcióknak elnevezett visszatérési értékük is lehet
func learnMultiple(x, y int) (sum, prod int) {
return x + y, x * y // visszatérünk két értékkel
/*
sum = x + y
prod = x * y
return
Ez ugyanezzel az eredménnyel járt volna, mint a fenti sor.
Üres return esetén, az elnevezett visszatérési változók
aktuális értékeikkel térnek vissza. */
}
// Beépített típusok
func learnTypes() {
// Rövid deklarás az esetek többségében elég lesz a változókhoz
s := "Tanulj Go-t!" // string típus
s2 := `A "nyers" stringekben lehetnek
újsorok is!` // de ettől még ez is ugyanolyan string mint az s, nincs külön típusa
// nem ASCII karakterek. Minden Go forrás UTF-8 és a stringek is azok.
g := 'Σ' // rúna(rune) típus, megegyezik az uint32-vel, egy UTF-8 karaktert tárol
f := 3.14195 // float64, az IEEE-754 szabványnak megfelelő 64-bites lebegőpontos szám
c := 3 + 4i // complex128, belsőleg két float64-el tárolva
// Var szintaxis változó típus definiálással
var u uint = 7 // unsigned, az implementáció dönti el mekkora, akárcsak az int-nél
var pi float32 = 22. / 7
// Rövid deklarásnál átalakítás is lehetséges
n := byte('\n') // byte típus, ami megegyezik az uint8-al
// A tömböknek fordítás-időben fixált méretük van
var a4 [4]int // egy tömb 4 int-tel, mind 0-ra inicializálva
a3 := [...]int{3, 1, 5} // egy tömb 3 int-tel, láthatóan inicalizálva egyedi értékekre
// Szeleteknek dinamikus a méretük. A szeleteknek és a tömböknek is meg vannak az előnyeik
// de a szeleteket sokkal gyakrabban használjuk.
s3 := []int{4, 5, 9} // vesd össze a3-al, nincsenek pontok.
s4 := make([]int, 4) // allokál 4 int-et, mind 0-ra inicializálva
var d2 [][]float64 // ez csak deklaráció, semmi sincs még allokálva
bs := []byte("a slice") // típus konverzió szintaxisa
p, q := learnMemory() // deklarál két mutatót (p,q), két int-re
fmt.Println(*p, *q) // * követi a mutatót. Ez a sor kiírja a két int értékét.
// A map a dinamikusan növelhető asszociatív tömb része a nyelvnek, hasonlít
// a hash és dictionary típusokra más nyelvekben.
m := map[string]int{"three": 3, "four": 4}
m["one"] = 1
// A felhasználatlan változók fordítás-idejű hibát okoznak a Go-ban.
// Az aláhúzással "használod" a változókat, de eldobod az értéküket.
_, _, _, _, _, _, _, _, _ = s2, g, f, u, pi, n, a3, s4, bs
// Kiíratás is természetesen használatnak minősül
fmt.Println(s, c, a4, s3, d2, m)
learnFlowControl()
}
// A Go nyelv teljesen szemétgyűjtött (garbage-collected). Megtalálhatók benne mutatók, de nincs mutató aritmetika.
// Ez azt jelenti, hogy üres mutatóval még mindig hibázhatsz, de hozzáadni/műveleteket végezni már nem lehet.
func learnMemory() (p, q *int) {
// Elnevezett visszatérési változóknak int-re mutató a típusa
p = new(int) // a beépített "new" funkció, egy típusnak elegendő memóriát allokál, és visszaad rá egy mutatót.
// Az allokált int nullázva van, p többé nem üres mutató.
s := make([]int, 20) // allokáljunk 20 int változót egy memóriaterületen.
s[3] = 7 // adjunk értéket az egyiknek
r := -2 // hozzánk létre egy lokális változót
return &s[3], &r // A & megadja a memóriacímét a változónak
}
func expensiveComputation() int {
return 1e6
}
func learnFlowControl() {
// Az elágazásoknak kötelező a kapcsos zárójel, a zárójel nem szükséges.
if true {
fmt.Println("megmondtam")
}
// A kód formátumát a nyelvvel járó "go" parancssori program "go fmt" parancsa szabványosítja
if false {
// így lehet
} else {
// if/else-t csinálni
}
// Használjunk switchet a hosszabb elágazások alkalmazása helyett.
x := 1
switch x {
case 0:
case 1:
// Az "esetek" nem "esnek át", tehát
case 2:
// ez nem fog lefutni, nincs szükség break-ekre.
}
// A for ciklus sem használ zárójeleket
for x := 0; x < 3; x++ {
fmt.Println("iteráció", x)
}
// itt az x == 1.
// A for az egyetlen ciklus fajta a Go-ban, de több formája van.
for { // végtelen ciklus
break // csak vicceltem
continue // soha nem fut le
}
// Akárcsak a for-nál, az if-ben is lehet rövid deklarással egy lokális változót létrehozni
// ami az blokk összes if/else-n keresztül érvényes marad.
if y := expensiveComputation(); y > x {
x = y
}
// Függvényeket használhatjuk closure-ként is.
xBig := func() bool {
return x > 100 // a switch felett deklarált x-et használjuk itt
}
fmt.Println("xBig:", xBig()) // igaz (utoljára 1e6 lett az értéke az x-nek)
x /= 1e5 // így most már x == 10
fmt.Println("xBig:", xBig()) // 10 pedig kisebb mint 100, tehát hamis
// Ha nagyon-nagyon szükséges, akkor használhatjuk a jó öreg goto-t.
goto love
love:
learnInterfaces() // Itt kezdődnek az érdekes dolgok!
}
// Definiáljuk a Stringert egy olyan interfésznek, amelynek egy metódusa van, a String, ami visszatér egy stringgel.
type Stringer interface {
String() string
}
// Definiáljuk a pair-t egy olyan struktúrának amelynek két int változója van, x és y.
type pair struct {
x, y int
}
// Definiáljunk egy metódust a pair struktúrának, ezzel teljesítve a Stringer interf
func (p pair) String() string { // p lesz a "vevő"
// Sprintf az fmt csomag egy publikus függvénye, műkődése megegyezik a C-s megfelelőjével.
// A pontokkal érjük el a mindenkori p struktúra elemeit
return fmt.Sprintf("(%d, %d)", p.x, p.y)
}
func learnInterfaces() {
// A kapcsos zárójellel jelezzük, hogy egyből inicializálni
// szeretnénk a struktúra változóit a sorrendnek megfelelően.
p := pair{3, 4}
fmt.Println(p.String()) // meghívjuk a p String metódusát.
var i Stringer // deklaráljuk i-t Stringer típusú interfésznek
i = p // lehetséges, mert a pair struktúra eleget tesz a Stringer interfésznek
// Meghívjuk i String metódusát, az eredmény ugyanaz, mint az előbb.
fmt.Println(i.String())
// Az fmt csomag funckciói automatikusan meghívják a String funkciót
// hogy megtudják egy objektum szöveges reprezentációját.
fmt.Println(p) // ugyan az az eredmény mint az előbb, a Println meghívja a String metódust.
fmt.Println(i) // dettó
learnErrorHandling()
}
func learnErrorHandling() {
// ", ok" szokásos megoldás arra, hogy jól működött-e a függvény.
m := map[int]string{3: "three", 4: "four"}
if x, ok := m[1]; !ok { // ok hamis lesz, mert az 1 nincs benne a map-ban.
fmt.Println("nincs meg")
} else {
fmt.Print(x) // x lenne az érték, ha benne lenne a map-ban.
}
// A hiba érték többet is elmond a függvény kimeneteléről, mint hogy minden "ok" volt-e
if _, err := strconv.Atoi("non-int"); err != nil { // _ eldobja az értéket, úgy se lesz jó jelen esetben
// kiírja, hogy "strconv.ParseInt: parsing "non-int": invalid syntax"
fmt.Println(err)
}
// Az interfészekre még visszatérünk, addig is jöjjön a konkurens programozás!
learnConcurrency()
}
// c egy csatorna, egy konkurens-biztos kommunikációs objektum.
func inc(i int, c chan int) {
c <- i + 1 // <- a "küldés" operátor, ha a bal oldalán csatorna van, így i+1-et küld be a csatornába
}
// Az inc-et fogjuk arra használni, hogy konkurensen megnöveljünk számokat
func learnConcurrency() {
// Ugyan az a make funkció amivel korábban szeleteket hoztunk létre.
// Make allokál mapokat, szeleteket és csatornákat.
c := make(chan int)
// Indítsunk három konkurens goroutine-t. A számok konkurensen lesznek
// megnövelve, ha a számítógép képes rá és jól be van állítva, akkor pedig paralellizálva/egymás mellett.
// Mind a 3 ugyanabba a csatornába küldi az eredményeket.
go inc(0, c) // A go utasítás indít el goroutine-okat.
go inc(10, c)
go inc(-805, c)
// Beolvassuk 3x a csatornából az eredményeket és kiírjuk őket a kimenetre.
// Nem lehet tudni milyen sorrendben fognak érkezni az eredmények!
fmt.Println(<-c, <-c, <-c) // hogyha a jobb oldalon csatorna van, akkor a "<-" a beolvasó/kapó operátor
cs := make(chan string) // még egy csatorna, ez stringekkel kommunikál
cc := make(chan chan string) // egy csatorna csatornával
go func() { c <- 84 }() // indítsunk egy új goroutine-t, csak azért hogy küldjünk egy számot
go func() { cs <- "wordy" }() // ugyanez, csak a cs csatornába stringet küldünk
// A select olyan mint a switch, csak feltételek helyett csatorna műveletek vannak.
// Véletlenszerűen kiválasztja az első olyan esetet, ahol létrejöhet kommunikáció.
select {
case i := <-c: // a megkapott értéket el lehet tárolni egy változóban
fmt.Println("ez egy", i)
case <-cs: // vagy el lehet dobni az értékét
fmt.Println("ez egy string volt")
case <-cc: // üres csatorna, soha nem fog rajta semmi se érkezni
fmt.Println("sose futok le :'( ")
}
// Ezen a ponton vagy c vagy a cs goroutineja lefutott.
// Amelyik hamarabb végzett, annak a megfelelő case-e lefutott, a másik blokkolva vár.
learnWebProgramming() // Go képes rá. Te is képes akarsz rá lenni.
}
// Egy funkció a http csomagból elindít egy webszervert.
func learnWebProgramming() {
// A ListenAndServe első paramétre egy TCP port, amin kiszolgálunk majd.
// Második paramétere egy interfész, pontosabban a http.Handler interfész.
err := http.ListenAndServe(":8080", pair{})
fmt.Println(err) // nem felejtük el kiírni az esetleges hibákat!
}
// Csináljunk a pair-ból egy http.Handler-t úgy, hogy implementáljuk az egyetlen metódusát a ServeHTTP-t.
func (p pair) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// Minden kapcsolatra elküldjük ezt a http.ResponseWriter-el
w.Write([]byte("Megtanultad a Go-t Y perc alatt!"))
}
```
## További olvasmányok
Minden Go-val kapcsolatos megtaláható a [hivatalos Go weboldalon](http://golang.org/).
Ott követhetsz egy tutorialt, játszhatsz a nyelvvel az interneten és sok érdekességet olvashatsz.
A nyelv specifikációját kifejezetten érdemes olvasni, viszonylag rövid és sokat tanul belőle az ember.
Ha pedig jobban bele akarod vetni magad a Go-ba, akkor a standard könyvtárban a legjobb praktikákat kilesheted.
TIPP: a dokumentációban kattints egy funkció nevére és rögtön megmutatja a hozzá tartozó kódot!
|