W tym artykule omówimy dwa tematy, bez których programowanie jest niemożliwe: typy oraz instrukcje sterujące. Golang idzie w kierunku maksymalnej prostoty, lecz nie prostactwa. W związku z tym typów nie wbudowano zbyt wiele, a instrukcji sterujących jest ledwie kilka. Co ważne, nie ujmuje to możliwościom tego języka.
Typy proste
Golang ma prosty system typów podstawowych, które możemy wykorzystać w naszych programach. Oczywiście nie ze wszystkich korzysta się na co dzień, lecz dobrze wiedzieć o ich istnieniu. Typy proste w golang wyglądają następująco:
- bool – odpowiadająca za prawdę/fałsz (true/false),
- string – tekst,
- int – liczba całkowita wraz z różnymi zakresami: int8, int16, int32 oraz int64,
- uint – liczba naturalna (czyli bez liczb ujemnych) wraz z różnymi zakresami: int8, int16, int32 oraz int64,
- float32 oraz float64 – liczby zmiennoprzecinkowe,
- complex64 oraz complex128 – liczby z częścią urojoną (czyli np. a + bi).
Nie będziemy od razu omawiać wszystkich typów, gdyż jest to nudne i… niepotrzebne. Przynajmniej na początku. Przyjrzyjmy się zatem programowi pokazującemu, w jaki sposób można stworzyć zmienne różnego typu oraz wyświetlić ich wartość.
func main() { fmt.Printf("Type: bool Value: %v\n", bool(true)) fmt.Printf("Type: string Value: %v\n", string("hello, golang")) fmt.Printf("Type: int Value: %v\n", int(8)) fmt.Printf("Type: float64 Value: %v\n", float64(15.6)) }
Użyłem tutaj trochę bardziej gadatliwego sposobu tworzenia tych zmiennych. Można to też uprościć do formy jak poniżej:
func main() { fmt.Printf("Type: bool Value: %v\n", true) fmt.Printf("Type: string Value: %v\n", "hello, golang") fmt.Printf("Type: int Value: %v\n", 8) fmt.Printf("Type: float64 Value: %v\n", 15.6) }
Golang jest w stanie domyślić się typu zmiennej, której używamy. To pierwszy moment, w którym ten język ułatwia nam pracę, robiąc coś za nas. Gdy deklarujemy jakąś wartość i zapisujemy ją do zmiennej, to nie musimy podawać jej typu. Kompilator wykona operację automatycznie.
Dzięki temu mechanizmowi możemy zainicjować zmienną na kilka różnych sposobów:
var someInt int = 123 var anotherInt = 123 andAnotherInt := 123
Te trzy zapisy są równoważne. W pierwszym przykładzie przed nazwą zmiennej używamy słowa kluczowego var
, następnie deklarujemy nazwę zmiennej oraz jej typ. Na końcu, po znaku równości, podajemy interesującą nas wartość. Drugi zapis jest trochę prostszy, gdyż pomijamy typ zmiennej – kompilator domyśli się go za nas na podstawie tego, co znajduje się po prawej stronie znaku równości.
Trzeci zapis jest najbardziej zwięzły, gdyż pomija całkowicie zarówno typ, jak i słowo kluczowe var
, lecz przed znakiem równości dodany jest dwukropek. Przy owym dwukropku na chwilę się zatrzymamy.
Przy tym zapisie dwukropek dajemy tylko wtedy, gdy tworzymy nową zmienną, co znaczy, że gdy przypisujemy nową wartość do istniejącej zmiennej, to dwukropek pomijamy. W związku z tym poprawny będzie zapis jak poniżej:
var myVariable := 1234 // ... myVariable = 4321
Ostatnim typem, który omówimy, jest interface{}
, czyli pusty interfejs. Zmienna tego typu może zawierać wszystko – może to być liczba całkowita, liczba zmiennoprzecinkowa czy struktura. Powinieneś starać się unikać stosowania pustego interfejsu, gdyż często jest to zła praktyka. Jednakże czasami okazuje się bardzo pomocna i należy pamiętać o jej istnieniu.
var myVariable interface{} // I can be anything myVariable = 4321 myVariable = "juppi" myVariable = 1.5
Instrukcje sterujące
Jeśli znamy już cały wachlarz typów zmiennych, możemy przejść do instrukcji sterujących. W języku golang, w związku z jego prostotą, nie ma ich za wiele. Omówmy więc po kolei każdą z nich.
Instrukcja warunkowa if
Praktycznie nie ma programu bez warunków. Pierwszą instrukcją warunkową, jaką poznamy, jest instrukcja if
, która wygląda następująco:
myVariable := 123 if myVariable == 321 { fmt.Println("we are equal") }
To, o czym należy pamiętać, to fakt, że rozpoczynająca klamra winna być w tej samej linii co słówko if
. Jeśli będziemy chcieli zapisać ją w nowej linii, nastąpi błąd kompilacji.
myVariable := 123 if myVariable == 321 { // błąd – nie skompiluje się! fmt.Println("we are equal") }
Bardzo pomocne jest także to, że jeżeli zastąpimy podwójny znak równości pojedynczym, to również otrzymamy błąd. Ma to zapobiec sytuacjom, w których zapominamy dodać ten znak i musimy poświęcić trochę czasu (oraz nerwów) na znalezienie błędu.
myVariable := 123 if myVariable = 321 { fmt.Println("we are equal") }
Co ciekawe, jesteśmy w stanie wewnątrz warunku zadeklarować zmienną. Operacja ta pozwoli nam skrócić nieco kod oraz sprawi, że ten warunek będzie bardziej czytelny. Przypisanie wartości zmiennej oraz warunek oddzielamy znakiem średnika.
if err := someFunction(); err != nil { fmt.Printf("no error") }
Możemy też oczywiście napisać kod, który wykona się, gdy warunek zawarty w „if” nie będzie spełniony. Obrazuje to poniższy przykład.
myVariable := 123 if myVariable == 321 { fmt.Println("we are equal") } else { fmt.Println("we are NOT equal 321") }
I tutaj warto pamiętać o tym, że klamra otwierająca powinna być w tej samej linii co słówko kluczowe else
. W przeciwnym wypadku otrzymamy błąd kompilacji.
Instrukcja sterująca switch
Inną bardzo prostą instrukcją sterującą jest instrukcja switch. Można o niej powiedzieć to, że jest inną formą zapisu kombinacji if–else–if–else. To oznacza, że każdego switcha można zastąpić szeregiem if–else, jak i na odwrót.
animal := "dog" switch animal { case "cat": fmt.Println("Cats rulez!") break case "dog": fmt.Println("Dogs rulez!") break case "cow": fmt.Println("Muuuu rulez!") break }
Gdy żaden z przypadków nie wystąpił, to możemy użyć instrukcji default
, która zostanie wykonana właśnie w takiej sytuacji.
animal := "chicken" switch animal { case "cat": fmt.Println("Cats rulez!") break case "dog": fmt.Println("Dogs rulez!") break case "cow": fmt.Println("Muuuu rulez!") break default: fmt.Println("I do not know the animal…") }
Switche są często używane do wykonywania pewnych operacji w zależności od typu. Typ danej zmiennej można odczytać, pisząc myVariable.(type)
.
var myVariable interface{} myVariable = 123 switch a := myVariable.(type) { case int: fmt.Println("I am an integer!", a) case string: fmt.Println("I am a string, cool", a) default: fmt.Println("I do not know what type I am, but I am not a string or int", a) }
Podsumowanie
Istnieje też inna instrukcja sterująca, a mianowicie select
, lecz ją zostawiam na jedną z kolejnych lekcji. Jak widać, zarówno typy, jak i instrukcje sterujące są bardzo proste i stosuje się je podobnie jak w innych językach. Zachęcam do eksperymentowania i pobawienia się tym, czego się nauczyłaś/nauczyłeś dzisiaj.
Tutorial idzie w równie dobrym kierunku jak Goalng. Gratuluję talentu prostego przekazywania wiedzy.
Drobna uwaga: nie działa ostatni link do play.golang.org
dziękuję bardzo za dobre słowo! Robim co mogiem :D