Programovací jazyk Go je opensource projekt zameraný na zjednodušenie programovania. Go je expresívny, stručný, čistý a efektívny. Jeho súbežné mechanizmy umožňujú ľahko písať programy, ktoré využijú čo najviac z viacjadrových a sieťových zariadení, zatiaľ čo nový typ systému umožňuje flexibilné a modulárne budovanie programu. Go sa zostavuje rýchlo do strojového kódu, napriek tomu má výhodu garbage collection a silu run-time. Je to rýchly, staticky napísaný, skompilovaný jazyk, ktorý sa chová ako by bol dynamického typu, interpretovaný jazykom.
Go efektívne - 2.diel
golang.cz
Jednou z neobvyklých vlastností Go je, že funkcie a metódy môžu vrátiť viac hodnôt. Túto vlastnosť je možné použiť na zlepšenie pár nemotorný štýlov v programe C: -band error vracia (napr. -1 pre EOF) a ktorým sa mení argument.
V Go, môže funkcia Write vrátiť počet a chybu: hlavička funkcie *File.Write v balíčku OS
Ako popisuje dokumentácia, funkcia vráti počet zapísaných bitov a ne-nilError (nenulový error. V Go za zapisuje null ako nil) pokiaľ n != len(b)
Následujúci príklad ukazuje funkciu, ktorá preberá pole znakov a index. Vráti hodnotu na zadanom indexe a ako druhú návratovú hodnotu vráti následujúci index.
Následujúca funkcia by sa dala použiť na vyhľadanie číselných obsahov v poli:
Návratové parametre môžu byť v jazyku Go pomenované rovnako ako argumenty. Pre prehľadnejšie používanie predchodzej funkcie by sme ju mohli upraviť na:
Kedže názvy návratových parametrov sa zobrazujú v dokumentácii, je z takejto funkcie hneď zrejmé, čo predstavuje ktorá hodnota.
Takto inicializované premenné sú rovnako plnohodnotné ako argumenty. Ich inicializácia je automatická, a tak ich stačí úž len nastaviť. Ich návratnosť je v takomto prípade rovnako automatická. Pokiaľ nebudú nastavené, použije sa ich defaultná hodnota, čo je vo väčšine prípadov nil.
Je tu vezia funkcie io.ReadFull ktorá to robí týmto spôsobom.
V Go môžete nájsť nový príkaz defer, ktorý má na starosti odkladanie volaní funkcií či metód. Je to neobvyklý, ale účinný spôsob ako riešiť situácie, kde musíte vykonať danú akciu bez ohľadu na to, akou cestou funkcia vráti výsledok. Je tu jedna ukážka ktorá to názorne používa na uzatvorenie súboru.
Odložená funkcia f.Close má dve výhody. Za prvé, nikdy nezabudneme zatvoriť súbor, čo je častá chyba hlavne keď pridávame vetvenie do funkcie. Za druhé, uzatváracia funkcia je umiestnená v blízkosti tej otváracej, čo je omnoho prehľadnejšie ako by bola umiestnená na konci funkcie.
Odložené volania sa vykonávanú odzadu, to jest, že posledná vložená sa vykoná ako prvá, viď následujúci príklad, ktorý na výsledku vráti 4 3 2 1 0 :
Odložená funkcia sa vyhodnotí až pri vyhodnotení deferu, nie pri vyhodnotení volania funkcie, čo dokazuje tento príklad:
ktorý vo výsledku vráti
V sekcii panic a recover sa pozrieme na ďalšie možnosti využitia.
Go má 2 alokačné príkazy, zabudované funkcie new a make. Robia rozdielne veci, a platia pre rozdielne typy, čo vás môže zmiasť, avšak pravidlá sú jednoduché. Ako prvé si objasníme new. Jedná sa o zabudovanú funkciu obdobnú ako v iných jazykoch. new(T) alokuje nulovú pamäť pre položku T a vráti jej adresu - hodnotu typu *T. V go terminológií : vráti ukazovateľ na novovytvorenú nulovú hodnotu typu T.
Skutočnosť, že vrátená pamäť pomocou new je nulová, môže byť užitočná vzhľadom k tomu že môže byť použitá bez dalšej inicializácie. To znamená, že používaťeľ dátovej štruktúry môže vytvoriť jednu pomocou new a hneď ju používať. Napríklad, dokumentácia k bytes.Buffer uvádza, že "nulová hodnota pre buffer je prázdny buffer pripravený na použitie". Podobne sync.Mute nemá explicitný konštruktor ani Init metódu, namiesto toho, nulová hodnota pre sync.Mute je definovaná pre odomknutie mutexu.
Nulová hodnota-je-užitočná vlastnosť pracujúca transparentne. Zoberme si tento príklad:
Hodnoty typu SyncedBuffer sú taktiež pripravené na použitie ihneď po alokovaní alebo hneď po deklarácií. V ďalšom kóde, p aj v budú pracovať korektne bez nutných budúcich opatrení.
Niekedy nieje nulová hodnota vhodná a inicializačný konštruktér je nutný, ako v tejto ukážke vytiahnutej z balíka os.
Je tu však veľa nastavovacích miest. Môžeme jednoducho použiť composite literal, ktorý zakaždým vytvorí novú inštantciu.
Všimnite si, že narozdiel od C, je úplne v poriadku navrátiť adresu lokálnej premennej; umiestnenie asociované pomocou premennej pretrváva aj po skončení funkcie. V skutočnosti, hovoríme o adrese kompozitného literálu alokovaného četsrtvou instanciou s každým vykonaním, takže môžeme skombinovať posledné dva riadky.
Vlastnosti (fields) kompozitného literála sú nastavené mimo poradia, a názvy sa musia zhodovať. Avšak pri označení elementov explicitne ako páry vlastnost:hodnota môže byť poradie a názvy ľubovolné, pričom nenastavené hodnoty ostanú nulové. Takto by sme mohlo nastaviť :
V limitovanom prípade, keď composite literal neobsahuje žiadne vlastnosti, je vytvorená nulová hodnota pre daný typ. Výrazy new(File) a &File{} sú si ekvivalentné.
Kompozitné literály môžu byť taktiež vytvorené pre polia, listy a mapy, z pármi vlastností ako indexy, alebo mapovými indexami. V tejto ukážke, Inicializácia pracuje bez ohľadu na hodnoty od Enone, Eio a Einval.
Zvyšok oficiálneho návodu je napísaného dosť nezrozumiteľne, čo myslím že sa prestáva hodiť do tohto článku. Preto prosím vyčkajte až natrafím na kvalitnejšie návody a podelím sa o ne, alebo prejdite na oficiálnu stránku.
golang.cz
Funkcie
Multiple return values
Jednou z neobvyklých vlastností Go je, že funkcie a metódy môžu vrátiť viac hodnôt. Túto vlastnosť je možné použiť na zlepšenie pár nemotorný štýlov v programe C: -band error vracia (napr. -1 pre EOF) a ktorým sa mení argument.
V Go, môže funkcia Write vrátiť počet a chybu: hlavička funkcie *File.Write v balíčku OS
func (file *File) Write(b []byte) (n int, err Error)
Ako popisuje dokumentácia, funkcia vráti počet zapísaných bitov a ne-nilError (nenulový error. V Go za zapisuje null ako nil) pokiaľ n != len(b)
Následujúci príklad ukazuje funkciu, ktorá preberá pole znakov a index. Vráti hodnotu na zadanom indexe a ako druhú návratovú hodnotu vráti následujúci index.
func nextInt(b []byte, i int) (int, int) {
for ; i < len(b) && !isDigit(b[ i ]); i++ {
}
x := 0
for ; i < len(b) && isDigit(b[ i ]); i++ {
x = x*10 + int(b[ i ])-"0"
}
return x, i
}
for ; i < len(b) && !isDigit(b[ i ]); i++ {
}
x := 0
for ; i < len(b) && isDigit(b[ i ]); i++ {
x = x*10 + int(b[ i ])-"0"
}
return x, i
}
Následujúca funkcia by sa dala použiť na vyhľadanie číselných obsahov v poli:
for i := 0; i < len(a); {
x, i = nextInt(a, i)
fmt.Println(x)
}
x, i = nextInt(a, i)
fmt.Println(x)
}
Pomenovanie návratových parametrov
Návratové parametre môžu byť v jazyku Go pomenované rovnako ako argumenty. Pre prehľadnejšie používanie predchodzej funkcie by sme ju mohli upraviť na:
func nextInt(b []byte, pos int) (value, nextPos int) {
...
...
Kedže názvy návratových parametrov sa zobrazujú v dokumentácii, je z takejto funkcie hneď zrejmé, čo predstavuje ktorá hodnota.
Takto inicializované premenné sú rovnako plnohodnotné ako argumenty. Ich inicializácia je automatická, a tak ich stačí úž len nastaviť. Ich návratnosť je v takomto prípade rovnako automatická. Pokiaľ nebudú nastavené, použije sa ich defaultná hodnota, čo je vo väčšine prípadov nil.
Je tu vezia funkcie io.ReadFull ktorá to robí týmto spôsobom.
func ReadFull(r Reader, buf []byte) (n int, err os.Error) {
for len(buf) > 0 && err == nil {
var nr int
nr, err = r.Read(buf)
n += nr
buf = buf[ nr:len(buf) ]
}
return
}
for len(buf) > 0 && err == nil {
var nr int
nr, err = r.Read(buf)
n += nr
buf = buf[ nr:len(buf) ]
}
return
}
Defer - zdržanie
V Go môžete nájsť nový príkaz defer, ktorý má na starosti odkladanie volaní funkcií či metód. Je to neobvyklý, ale účinný spôsob ako riešiť situácie, kde musíte vykonať danú akciu bez ohľadu na to, akou cestou funkcia vráti výsledok. Je tu jedna ukážka ktorá to názorne používa na uzatvorenie súboru.
// Contents returns the files contents as a string.
func Contents(filename string) (string, os.Error) {
f, err := os.Open(filename)
if err != nil {
return "", err
}
defer f.Close() // f.Close will run when were finished.
var result []byte
buf := make([]byte, 100)
for {
n, err := f.Read(buf[ 0: ])
result = append(result, buf[ 0:n ]...) // append is discussed later.
if err != nil {
if err == os.EOF {
break
}
return "", err // f will be closed if we return here.
}
}
return string(result), nil // f will be closed if we return here.
}
func Contents(filename string) (string, os.Error) {
f, err := os.Open(filename)
if err != nil {
return "", err
}
defer f.Close() // f.Close will run when were finished.
var result []byte
buf := make([]byte, 100)
for {
n, err := f.Read(buf[ 0: ])
result = append(result, buf[ 0:n ]...) // append is discussed later.
if err != nil {
if err == os.EOF {
break
}
return "", err // f will be closed if we return here.
}
}
return string(result), nil // f will be closed if we return here.
}
Odložená funkcia f.Close má dve výhody. Za prvé, nikdy nezabudneme zatvoriť súbor, čo je častá chyba hlavne keď pridávame vetvenie do funkcie. Za druhé, uzatváracia funkcia je umiestnená v blízkosti tej otváracej, čo je omnoho prehľadnejšie ako by bola umiestnená na konci funkcie.
Odložené volania sa vykonávanú odzadu, to jest, že posledná vložená sa vykoná ako prvá, viď následujúci príklad, ktorý na výsledku vráti 4 3 2 1 0 :
for i := 0; i < 5; i++ {
defer fmt.Printf("%d ", i)
}
defer fmt.Printf("%d ", i)
}
Odložená funkcia sa vyhodnotí až pri vyhodnotení deferu, nie pri vyhodnotení volania funkcie, čo dokazuje tento príklad:
func trace(s string) string {
fmt.Println("entering:", s)
return s
}
func un(s string) {
fmt.Println("leaving:", s)
}
func a() {
defer un(trace("a"))
fmt.Println("in a")
}
func b() {
defer un(trace("b"))
fmt.Println("in b")
a()
}
func main() {
b()
}
fmt.Println("entering:", s)
return s
}
func un(s string) {
fmt.Println("leaving:", s)
}
func a() {
defer un(trace("a"))
fmt.Println("in a")
}
func b() {
defer un(trace("b"))
fmt.Println("in b")
a()
}
func main() {
b()
}
ktorý vo výsledku vráti
entering: b
in b
entering: a
in a
leaving: a
leaving: b
in b
entering: a
in a
leaving: a
leaving: b
V sekcii panic a recover sa pozrieme na ďalšie možnosti využitia.
Data
Alokácia pomocou new
Go má 2 alokačné príkazy, zabudované funkcie new a make. Robia rozdielne veci, a platia pre rozdielne typy, čo vás môže zmiasť, avšak pravidlá sú jednoduché. Ako prvé si objasníme new. Jedná sa o zabudovanú funkciu obdobnú ako v iných jazykoch. new(T) alokuje nulovú pamäť pre položku T a vráti jej adresu - hodnotu typu *T. V go terminológií : vráti ukazovateľ na novovytvorenú nulovú hodnotu typu T.
Skutočnosť, že vrátená pamäť pomocou new je nulová, môže byť užitočná vzhľadom k tomu že môže byť použitá bez dalšej inicializácie. To znamená, že používaťeľ dátovej štruktúry môže vytvoriť jednu pomocou new a hneď ju používať. Napríklad, dokumentácia k bytes.Buffer uvádza, že "nulová hodnota pre buffer je prázdny buffer pripravený na použitie". Podobne sync.Mute nemá explicitný konštruktor ani Init metódu, namiesto toho, nulová hodnota pre sync.Mute je definovaná pre odomknutie mutexu.
Nulová hodnota-je-užitočná vlastnosť pracujúca transparentne. Zoberme si tento príklad:
type SyncedBuffer struct {
lock sync.Mutex
buffer bytes.Buffer
}
lock sync.Mutex
buffer bytes.Buffer
}
Hodnoty typu SyncedBuffer sú taktiež pripravené na použitie ihneď po alokovaní alebo hneď po deklarácií. V ďalšom kóde, p aj v budú pracovať korektne bez nutných budúcich opatrení.
p := new(SyncedBuffer) // type *SyncedBuffer
var v SyncedBuffer // type SyncedBuffer
var v SyncedBuffer // type SyncedBuffer
Konštruktéri a kompozitné literály
Niekedy nieje nulová hodnota vhodná a inicializačný konštruktér je nutný, ako v tejto ukážke vytiahnutej z balíka os.
func NewFile(fd int, name string) *File {
if fd < 0 {
return nil
}
f := new(File)
f.fd = fd
f.name = name
f.dirinfo = nil
f.nepipe = 0
return f
}
if fd < 0 {
return nil
}
f := new(File)
f.fd = fd
f.name = name
f.dirinfo = nil
f.nepipe = 0
return f
}
Je tu však veľa nastavovacích miest. Môžeme jednoducho použiť composite literal, ktorý zakaždým vytvorí novú inštantciu.
func NewFile(fd int, name string) *File {
if fd < 0 {
return nil
}
f := File{fd, name, nil, 0}
return &f
}
if fd < 0 {
return nil
}
f := File{fd, name, nil, 0}
return &f
}
Všimnite si, že narozdiel od C, je úplne v poriadku navrátiť adresu lokálnej premennej; umiestnenie asociované pomocou premennej pretrváva aj po skončení funkcie. V skutočnosti, hovoríme o adrese kompozitného literálu alokovaného četsrtvou instanciou s každým vykonaním, takže môžeme skombinovať posledné dva riadky.
return &File{fd, name, nil, 0}
Vlastnosti (fields) kompozitného literála sú nastavené mimo poradia, a názvy sa musia zhodovať. Avšak pri označení elementov explicitne ako páry vlastnost:hodnota môže byť poradie a názvy ľubovolné, pričom nenastavené hodnoty ostanú nulové. Takto by sme mohlo nastaviť :
return &File{fd: fd, name: name}
V limitovanom prípade, keď composite literal neobsahuje žiadne vlastnosti, je vytvorená nulová hodnota pre daný typ. Výrazy new(File) a &File{} sú si ekvivalentné.
Kompozitné literály môžu byť taktiež vytvorené pre polia, listy a mapy, z pármi vlastností ako indexy, alebo mapovými indexami. V tejto ukážke, Inicializácia pracuje bez ohľadu na hodnoty od Enone, Eio a Einval.
a := [...]string {Enone: "no error", Eio: "Eio", Einval: "invalid argument"}
s := []string {Enone: "no error", Eio: "Eio", Einval: "invalid argument"}
m := map[int]string{Enone: "no error", Eio: "Eio", Einval: "invalid argument"}
s := []string {Enone: "no error", Eio: "Eio", Einval: "invalid argument"}
m := map[int]string{Enone: "no error", Eio: "Eio", Einval: "invalid argument"}
Zvyšok oficiálneho návodu je napísaného dosť nezrozumiteľne, čo myslím že sa prestáva hodiť do tohto článku. Preto prosím vyčkajte až natrafím na kvalitnejšie návody a podelím sa o ne, alebo prejdite na oficiálnu stránku.
Hodnocení +78
Líbí
Nelíbí
Přečteno 1035-krát
Líbí
NelíbíPřečteno 1035-krát
Komentáře
Přidat nový
Pro přispívání musíte být přihlášen
Zapsal Loric - 13.09.2011 09:56
Vidím, že ty se naučíš snad každý jazyk, o kterém uslyšíš :D Kolik jich už vlastně umíš?


