A Go programozási nyelv

Példaprogramok

Chat szerver és kliens

Az elkészített példaprogram egy chat szerver-kliens program. A kliensek be tudnak jelentkezni a szerverre, le tudjak kérdezni a bejelentkezett felhasználók listáját, beszélgetést tudnak kezdeményezni valamely másik felhasználóval. Egy kliens egyszerre több beszélgetésben is részt vehet, egy beszélgetésre küldött üzenetet a beszélgetésben résztvevő összes felhasználó megkapja. Egy beszélgetésbe fel lehet venni további felhasználókat, ki lehet lépni belőle.

A programot Linux operációs rendszeren, a gc fordító 8g (x86-os) változatával készítettem
Letöltés

Láng László (llk at inf elte hu)
2010 május

Párhuzamos rendezés

A Go nagyfokú támogatást nyújt a párhuzamossághoz, célként az egyik legalapvetőbb programfunkció, a rendezés párhuzamos változatának elkészítését tűztem ki célul.

Először egy egyszerűbb programot készítettem el, mely a számokat nem rendezi, hanem csupán összeadja (természetesen azt is párhuzamosan)

A program teszteléséhez szükségem volt bemenő adatokra. Ehhez készítettem egy olyan programot, mely véletlen számokat ír ki. Ennek a kimenetét irányítottam egy szövegfájlba, és ez lett a másik két program bemenete.

Ezután készült el a párhuzamos rendező.

A nem párhuzamos megvalósítás

func quickSort(data sort.Interface, lower int, upper int) { //pivot elem indexének kiszámítása var pivotId int = lower + (upper-lower) / 2 i, j := partition(data, lower, upper, pivotId) //újra meghívás if (lower < j) { quickSort(data, lower, j) } if (i < upper) { quickSort(data, i, upper) } }

A párhuzamos megvalósítás

func quickSortParallel(data sort.Interface, lower int, upper int, channel_in chan int, splitdepth int) { //pivot elem indexének kiszámítása var pivotId int = lower + (upper-lower) / 2 i, j := partition(data, lower, upper, pivotId) //saját csatorna készítése channel_own := make(chan int, 2) //újra meghívás waitthread := 0; if splitdepth == 0 || upper - lower < 100 { if (lower < j) { quickSort(data, lower, j) } if (i < upper) { quickSort(data, i, upper) } } else { if (lower < j) { go quickSortParallel(data, lower, j, channel_own, splitdepth - 1) waitthread++ } if (i < upper) { go quickSortParallel(data, i, upper, channel_own, splitdepth - 1) waitthread++ } } //bevárjuk, még elkészülnek az alprogramok for ; waitthread > 0; waitthread-- { <-channel_own } //jelezzük a hívó függvénynek, hogy kész channel_in <- 1 }

A programot a gc fordító 8g (x86-os) változatával készítettem, kezdetben Linux operációs rendszeren, viszont mivel itt a párhuzamosságot tesztelni nem volt módom, ezért áttértem a Windowsos fordítóra, ahol a Linux-on készített kód gond nélkül lefordult.

A programok forrásai az alábbi linkről tölthetőek le: Letöltés

Cséri Tamás (cseri at inf elte hu)
2010. június

Kétjátékos aknakereső

A kétjátékos aknakereső egy körökre osztott játék, melyben a játékosok célja az, hogy minél több aknát megtaláljanak a játéktérben. A játéktér 16x16-os négyzetrácsból áll (a méret átállítható). A négyzetrács néhány mezője tartalmaz aknákat. Összesen 53 akna van lerakva a rácsra (ez a szám is konfigurálható). A játék elején a játékosok nem ismerik a rács tartalmát, csak egy üres rácsot láthatnak. Egy kör során egy játékos kiválaszthat egy eddig ismeretlen mezőt és feltárhatja annak a tartalmát. Ha sikerült aknát találni, a következő körben szintén ő léphet. Ellenkező esetben feltárul, hogy az adott mező körüli 8 mező közül mennyiben van akna és a következő lépésben a másik játékos lép. A játéknak akkor van vége, ha az összes akna feltárolódott a rácsról.

package minefield import "rand" type Minefield struct { Rows, Cols, Mines int32 // The possible values of each field byte: // ? - unknown field // 0..8 - known field // x - field with a mine Fields [][]byte } func Create(rows, cols, mines int32) (field *Minefield) { field = new(Minefield) field.Rows, field.Cols, field.Mines = rows, cols, mines initialize(field) generate_mines(field) put_nums(field) return } func ToByteSlice(field *Minefield, bytes *[]byte) { *bytes = make([]byte, field.Rows*field.Cols) i := 0 for r := range field.Fields { for c := range field.Fields[r] { (*bytes)[i] = field.Fields[r][c] i += 1 } } } // Assumes that field has the correct Rows, Cols and Mines values func FromByteSlice(bytes []byte, field *Minefield) { i := 0 for r := range field.Fields { for c := range field.Fields[r] { field.Fields[r][c] = bytes[i] i += 1 } } } func initialize(field *Minefield) { field.Fields = make([][]byte, field.Rows) for i := range field.Fields { field.Fields[i] = make([]byte, field.Cols) } } func generate_mines(field *Minefield) { for m := 0; int32(m) < field.Mines; m++ { r, c := rand.Int31n(field.Rows), rand.Int31n(field.Cols) if field.Fields[r][c] != 0 { m -= 1 } else { field.Fields[r][c] = 'x' } } } func is_mine_at(r, c int, field *Minefield) bool { if (r < 0 || int32(r) >= field.Rows) { return false } if (c < 0 || int32(c) >= field.Cols) { return false } if (field.Fields[r][c] == 'x') { return true } return false } func put_nums(field *Minefield) { for r := 0; int32(r) < field.Rows; r++ { for c := 0; int32(c) < field.Cols; c++ { if field.Fields[r][c] == 'x' { continue } cnt := 0; for i := -1; i <= 1; i++ { for j := -1; j <= 1; j++ { if is_mine_at(r+i, c+j, field) { cnt += 1; } } } field.Fields[r][c] = byte(cnt) } } }

A programot Google 6g (x86_64) fordítójával készítettem Linux operációs rendszeren, amely szükségeltetik is a futattásához.

A program forrása az alábbi linkről tölthető le: Letöltés

Kezes Balázs (rblaster at inf elte hu)
2011. május

Duplikációk

A példaprogram hozzáfér a fájlrendszerhez. Az argumensként megadott könyvtárat rekurzívan bejárja és a hash szerint egyforma fájlokat kiírja.

Részlet a kódból.

// Egy path stringbol es egy Hash interfacebol, kiszamitsuk // a fajl tartalmanak hashet func getHash(path Path) (result string, err os.Error) { // uj hash szamito hash := sha1.New() // ha ki tudjuk nyitni a fajlt... if file, err := os.Open(string(path), os.O_RDONLY, 0); err == nil { // es be tudjuk masolni a tartalmat a hashelesre if _, err := io.Copy(hash, file); err == nil { // akkor van egy eredmenyunk result = encodeBase64(hash.Sum()) } } // return, amennyiben nil az eredmeny, vagy error return }

A program fordítás Ubuntu operációs rendszeren, a 8g fordítóval történt.
Letöltés

Varga Kristián (vk584 at inf elte hu)
2011 május

E-mail kereső

A program egy adott könyvtárból beolvassa a e-mail fájlokat amelyek az RFC-5322 által definiált formátumban vannak, majd a parancssori argumentumokban megadott szűrőfeltételeknek megfelelően kiírja azoknak a fájloknak a nevét, amely az összes szűrőfeltételnek megfeleltek. A szűrőfeltételek reguláris kifejezések, amelyek a feladó/küldő nevére illetve e-mail címére valamint a tárgyra és a levéltörzsre vonatozhatnak.

A forrás az alábbi linken érhető el:
Letöltés

Ispánovics Gábor Alex (galex at elte hu)
2012. május

Az adatcsatorna programozási tételének általános megvalósítása

Ez valójában nem program, hanem egy csomag, amely általánosított megvalósítást ad az adatcsatorna programozási tételére. A csomaghoz mellékelve található egy egyszerű példaprogram is, mely bemutatja a csomag használatát.

A feladat köznyelvi leírása: nagy számú adaton szeretnénk végrehajtani azonos műveletet, és a művelet több részművelet egymásutánjára (kompozíciójára) bontható. Ekkor (megfelelő számú processzor birtokában) a feladat lineáris időben (adatok száma + komponenesek száma) elvégezhető, ha minden komponenst egy processzor hajt végre, és ezek párhuzamosan dolgoznak a komponensek között haladó adatokon.

A csomag fő típusa az Adatcsatorna interface típus. Az interface egyetlen metódusa a Komponens(Adat, param interface{}) Adat szignatúrával rendelkezik. A használónak csak ezt kell megvalósítani. (Az Adat típus szinonima az interface{}-re).

A Komponens függvény írja le az összes műveleti komponens működését. Első paramétere a feldolgozandó adat, visszatérési értéke a transzformált adat. Második paramétere írja le azt, hogy ez melyik komponense az összetett függvénynek. Ez lehet pl. egyszerűen egy sorszám, ami alapján egy switch konstrukcióval választjuk a végrehajtandó műveletet, de lehet tetszőlegesen bonyolult egyéb érték is.

A csomagot olyan módon vehetjük használatba, hogy meghívjuk a csomag Start(Adatcsatorna, []Adat, params []interface{}) []Adat függvényét.
A függvény első paramétere nyilván az Adatcsatorna interfészt megvalósító saját típusunk. A második paraméter a feldolgozandó adatok sorozata. A harmadik paraméter (params) hossza határozza meg az egymás után fűzött komponensek számát, és a komponenseknek rendre a params elemei adódnak át a param paraméterben. A visszatérési érték a transzformált adatok sorozata.

A valódi párhuzamosításról, amennyiben szeretnénk kihasználni a lehetőséget, magunknak kell gondoskodnunk a párhuzamosítás szakaszban leírtak szerint.

A forrás az következő linken érhető el: adatcsatorna.zip

A program fordítása Windows 7 operációs rendszer alatt, a Go 1.0 fordító 64 bites változatával történt (ld. a Go letöltési oldala).

Bognár Bálint (bobqaai at inf elte hu)
2012. május

BlackJack játék

A program egy egyszemélyes BlackJack játék. A játékosnak lehetősége van a gép ellen játszani, mely során téteket rakhat, új lapot kérhet, vagy megállhat a játék során. A cél minél több pénz gyűjtése a kezdeti 100$-ból kiindulva. A program próbálja szemléltetni a Go nyelvben használható objektum orientált szemléleti elemeket. Bár a nyelv nem objektum orientált, így is megvalósíthatók annak egyes elemei.

A program fő adattípusai a Player amely a játékost reprezentálja, a BettingPlayer amely pénzzel rendelkező játékos (ebbe beágyazva található egy Player), a Card, ami egy kártyalapot reprezentál, és a Deck, amely a kártyatömböt reprezentálja.

A forrás az következő linken érhető el: blackjack.zip

A program fordítása Windows 7 operációs rendszer alatt, a Go 1.0 fordító 64 bites változatával történt (ld. a Go letöltési oldala).

Gyimesi Gábor (gygraai at inf elte hu)
2013. június

Mergesort példaprogram

A program a mergesort algoritmus segítségével rendez egy tömböt. A rendezés párhuzamosan történik goroutinok és csatornák használatával.

A programot Windows operációs rendszeren készítettem
Letöltés

Nagy Márton (nagymarci at hippy csoma elte hu)
2014. június

A termelő-fogyasztó probléma párhuzamosítása

A program a termelő-fogyasztó problémát modellezi, és több lépésben párhuzamosított megoldásokon keresztül készít méréseket a go eszköszkészletében elérhető benchmark lehetőségek segítségével. A következő eseteket valósítottam és mértem a gyorsulásukat.

Az általam mért eredmények a test.sh szkript futtatásával a maximálisan használható szálak variálásával (1, 2, 4, 8):
Testing on 1 OS thread testing: warning: no tests to run PASS Benchmark1Producer1Consumer1Channel 500 5978385 ns/op Benchmark10Producer1Consumer1Channel 500 4518666 ns/op Benchmark10Producer10Consumer1Channel 500 4106402 ns/op ok nyelvek-go-example/prodcons 8.749s ======================================= Testing on 2 OS thread testing: warning: no tests to run PASS Benchmark1Producer1Consumer1Channel-2 500 5992606 ns/op Benchmark10Producer1Consumer1Channel-2 500 4518715 ns/op Benchmark10Producer10Consumer1Channel-2 5000 526128 ns/op ok nyelvek-go-example/prodcons 9.074s ======================================= Testing on 4 OS thread testing: warning: no tests to run PASS Benchmark1Producer1Consumer1Channel-4 500 5992435 ns/op Benchmark10Producer1Consumer1Channel-4 500 4502196 ns/op Benchmark10Producer10Consumer1Channel-4 5000 528017 ns/op ok nyelvek-go-example/prodcons 9.066s ======================================= Testing on 8 OS thread testing: warning: no tests to run PASS Benchmark1Producer1Consumer1Channel-8 500 5988077 ns/op Benchmark10Producer1Consumer1Channel-8 500 4510752 ns/op Benchmark10Producer10Consumer1Channel-8 5000 516462 ns/op ok nyelvek-go-example/prodcons 9.027s =======================================

A programot Linux (Linux Mint 15) operációs rendszeren Go 1.2 használatával készítettem.
Letöltés

Keserű Zsolt (zsolooo at hippy csoma elte hu)
2014. május