Nasıl Ortaya Çıktı ?
Go programlama dili, Google tarafından 2007 yılından itibaren açık kaynak kodlu olarak Robert Griesemer, Ken Thompson ve Rob Pike tarafından başlatılan bir projedir. 2008 yılında Ian Lance Taylor ve Russ Cox bu projeye dahil oldular. Kasım 2009’da projenin varlığını bildirdiler. Go’nun ilk versiyonu Mart 2012’de yayınlanmıştır. 2015 yılından itibaren akıllı telefonlar için kullanılmaya başlanmıştır.
Thompson Amerikalı bir bilgisayar bilimcisidir. Thompson, Unix işletim sistemini tasarlayıp uyguladığı Bell Labs’ta çalıştı. 2006’dan beri Go programlama dilini birlikte icat ettiği Google’da çalışıyor.
Griesemer, İsviçreli bir bilgisayar bilimcisidir. Zürih Federal Teknoloji Enstitüsü olarak da bilinen, İsviçre’nin Zürih kentinde kurulu üniversitede lisansını ve doktorasını tamamladı.
Pike, Kanadalı bir programcı ve yazardır. Go programlama dili ve Unix ekibinin bir üyesi olduğu Bell Labs’daki çalışmaları ile tanınır.
Go aslında deney amaçlı ortaya çıktı. Amaç; diğer dillerin iyi özelliklerini korumak, ancak eleştiri alan kısımlarına çözüm üretmek üzere geliştirilmeye başlandı. Yaratıcıları ile yapılan görüşmelerde o zamanlarda çoğunlukla kullanılan C++ programlama dilinin sorunlarına çözüm olacak bir proje başlattıklarını söylenmiştir. Go projesi başlamadan önce Google, kendi projelerinde C, Java, C++, Python vs. bir çok yazılım dilini kullanıyorlardı. Performans sorunlarını o dilin yetebildiği oranda çözmeye çalıştılar. Kodun derlenme sürelerinin uzun olması, yaşanan performans problemleri, güvenlik zaafiyetleri, zaman yönetimi, daha iyi performans için daha fazla kaynak alımının artması Google ve 3 mühendisin Go deneysel projeyi ortaya çıkarmasını sağladı.
Go takımı ile tanışmak isteseniz https://www.youtube.com/watch?v=sln-gJaURzk linkindeki videoyu izleyebilirsiniz.
Go’nun Genel Yapısı Nasıldır ?
Dilin anlaşılır ve basit bir yapısı var. Dilde sadece 25 anahtar (keyword) bulunuyor.
C dilinde 37, C++ dilinde 84, Java dilinde 52, Python dilinde 33 anahtar mevcut.
Tanımlama (Declaration)
const, var, type, func , import , package
Kompozit Tipler (Composite Types)
chan, map, interface, struct
Kontrol
break, continue, case ,default, fallthrough, for, if, goto, return, select, switch, else, range
Fonksiyon
go, defer2
Tipler ve bazı “built-in” fonksiyonlar
append, bool, byte, cap, close, complex, complex64, complex128, uint16, copy, false, float32, float64, imag, int, int8, int16, uint32, int32, int64, iota, len, make, new, nil, panic, uint64, print, println, real, recover, string, true, uint, uint8, uintptr
Go dilini incelediğimizde jenerik bir yapıya sahip olmadığını görürüz. Jenerikler elbette kullanışlıdır. Ancak çalışma zamanının yarattığı karmaşıklık açısından bir maliyete sahip olacaktır. Geliştirici ekibinin elbetteki amacı bu değildi. Basitlik ve performans göz önünde bulundurularak tasarlanmıştı.
İlk Go kodunu yazdığınızda farkedeceğiniz, derlenme süresinin ne kadar hızlı olduğudur. Go Garbage Collector (Belleği Boşaltma İşlemi) mimarisine sahiptir. Hafıza (Memory) yönetimi Go tarafından sağlanır. Güçlü standart kütüphane yönetimine sahiptir.
Açık Kaynak Kodlu, Cross-Platform
Go tamamen açık kaynak kodludur. Go kaynak kodunu tümüyle inceleyebilirsiniz. Kaynak kodu Github üzerinde https://github.com/golang linkinden bulabilirsiniz.
OpenBSD, NetBSD, FreeBSD, Windows, Linux, MacOS, AIX, Android, Darwin, Dragonfly, Hurd, Illumos, Js, Nacl, Plan9, Solaris, Zos tarafından desteklenmektedir.
Go yaratıcılarının katkılarının yanı sıra, piyasada Go dilini kullanan büyük teknoloji firmalarının da Go’nun gelişimine katkıda bulunduğunu söyleyebiliriz.
Go’ya Eklenmemiş Yapılar Nelerdir?
Diğer programlama dillerinde olan bazı özellikler hız ve basitlik olması açısından Go’ya eklenmemiştir. Kalıtım (Inheritance), Method Aşırı Yükleme (Overloading), Jenerik Programlama, Çok Biçimlilik (Polymorphism) özellikleri Go’da yoktur.
Bknz: https://golang.org/doc/faq#generics
Go Map Operasyonları Neden Atomic Değil?
Go yaratıcıları map kullanımlarını güvensiz erişim şeklinde bırakıp bırakmamak konusunda uzun süre tartışmışlar. Yazının başında dediğim gibi hız, düşük maliyet Go’nun vizyonudur. Map’leri çoklu erişimlerde güvensiz bırakmışlar. Bu şekilde daha büyük veri yapılarında daha hızlı arama ve hesaplamalar yapılabilecektir.
Go Object-OrIented Bir Programlama Dili Midir?
Aslında bu sorunun cevabı yok. Hem evet hem hayır. Go’da yer alan tipler, methodlar, fonksiyonlar Object-Oriented Programlama dilinin bazı özelliklerini taşıyor. Go’da “object” olarak nitelendirilen bir yapı yok. Bunun yerine değişken tanımlarının ve methodların yer aldığı “struct” yapısı bulunuyor.
Go Neye Benziyor?
Bu konuda herkesin bir fikri olabilir. Ancak Go geliştiricileri bu konuda net bir açıklama yapmışlar. Söz dizimi (syntax) olarak çoğunlukla “C” dilinin yapısına benziyor. Tanımlama ve paket düzeni olarak Pascal/Modula/Oberon ailesinden alıntılar mevcut. Eş zamanlılık (concurrency) olarak Limbo diline benzerlik gösteriyor.
Bkz: https://golang.org/doc/faq#ancestors
Go’yu dünyada kullanan Firmalar Neler?
Bazı Yabancı Teknoloji Firmaları:
Docker
Koding
Dailymotion
SendGrid
SoundCloud
Dropbox
Medium
Google
Ubuntu
Uber
Twitch
Facebook
Bazı Yerli Teknoloji Firmaları:
put.io
LocRep
Optimum Yazılım
Mentornity, Inc.
Insider
Admongrel
Frigbo
Trendyol.com
Peak Games
Metglobal
MasomoGaming
Mos Teknoloji
Daha kapsamlı bilgiyi https://github.com/golang/go/wiki/GoUsers sayfasından edinebilirsiniz.
Go Üzerine Basit Örnekler
Yazının başında söylediğim gibi Go dili toplamda 25 anahtara sahip. Şimdi her bir anahtardan kod örnekleri vereceğim.
import
Go üzerinde herhangi bir referans göstermeden kullanılabilecek fonksiyonlar mevcuttur. Go’da “import” anahtar kelimesi ile kütüphaneleri referans gösterebiliriz. Paketler içerisinde yer alan tüm fonksiyonlar erişilebilir ve kullanılabilir hale gelir. Println() fonksiyonu ekrana girdiyi yazdırmak için kullanılır. Ancak bu fonksiyonu kullanabilmek için “fmt” paketinin import edilmesi gerekir.
package main
import (
"fmt"
)
func main() {
fmt.Println("I learn Go!")
}
struct
Object-Oriented programlama dillerindeki “object” anahtarına benzer bir yapısı vardır. Go’da Sınıf’a (Class) Struct diyebilirsiniz.
package main
import (
"fmt"
"strconv"
)
type Person struct {
Name string
Address string
Phone string
Age int
}
func main() {
var person *Person
person = &Person{Name:"Parta",Address:"IZMIR",Phone:"02322908811",Age:14}
fmt.Println("My Name is",person.Name,".I am at",person.Address,".My phone number is",person.Phone,"I am",strconv.Itoa(person.Age),"years old.")
}
const
Go’da statik tanımlamalar “const” anahtar kelimesi ile yapılabilmektedir. Gerek globalde gerekse lokal olarak const tanımı yapılabilir.
package main
import "fmt"
const (
Name = "Parta"
Sector = "Software"
Age = 14
BirthYear = 2006
)
const (
First = 5 * iota
Second
Third
)
func main() {
fmt.Println(Name)
const localnumber = 1881
fmt.Println(localnumber)
const a = "50"
fmt.Println(a)
fmt.Println(First)
fmt.Println(Second)
fmt.Println(Third)
}
Çıktı:
Parta
1881
50
0
5
10
var
Go’da değişken tanımları yapılırken herhangi bir değişken tipi belirtme zorunluluğu yoktur. Değişken tipi belirtileceği zaman “var” anahtar kelimesini kullanıyoruz.
package main
import "fmt"
func main() {
var a, b int = 1, 2
c:="3"
d:=4
e, f, g, h := true, false, 4.5,"yes"
fmt.Println(a, b, c, d, e, f, g, h)
}
Çıktı:
1 2 3 4 true false 4.5 yes
type
package main
import "fmt"
type Food interface {
Cook() bool
Mix() bool
Eat() bool
}
type Meat struct {
name string
cookTime int
}
func (m Meat) Cook() bool {
fmt.Printf("Food %s is started. It will be finished after %d seconds.\n",m.name,m.cookTime)
return true
}
func (m Meat) Mix() bool {
fmt.Printf("Food %s is being mixed.\n",m.name)
return true
}
func (m Meat) Eat() bool{
fmt.Printf("Food %s started to be eaten.\n",m.name)
return true
}
func main() {
var m *Meat
m = &Meat{name:"Meatball",cookTime:100}
m.Cook()
m.Mix()
m.Eat()
fmt.Println("All is ok!")
}
Çıktı:
Food Meatball is started. It will be finished after 100 seconds.
Food Meatball is being mixed.
Food Meatball started to be eaten.
All is ok!
func
Go’da fonksiyon tanımlamaları “func” anahtar kelimesi ile başlar.
package main
import "fmt"
// A function that sum all elements in array
func Sum(numbers []int) int{
count:=0
for _,cnt :=range numbers {
count += cnt
}
return count
}
func main() {
var elements = []int{1,2,3,4,5}
fmt.Println(Sum(elements))
}
Çıktı:
15
package
Go yazılımcıları tarafından oluşturulmuş paketler import edilerek kullanılabilir.
“main” paketi çalıştırılabilir bir binary program yapmak için kullanılır.
package main
import (
"strings"
"github.com/google/gopacket"
"fmt"
)
chan
Go’da eş zamanlılık mimarisi gerçekten çok iyi işlenmiş. Aynı anda birden fazla işlem sinyalizasyon ile gerçekleştirilebilir.
“chan1 := make(chan int)” ile kanal oluşturulur.
“x:= <-chan1” ile veri alınır. Ok işareti verinin yönünü göstermektedir. “c <- count” ile veri kanala gönderilir. Aşağıda görüleceği üzere sum fonksiyonunda return kullanılmamış, count değeri bir kanala gönderilmiştir.
package main
import "fmt"
// Function that sum of all integer array elements
func sum(numbers []int, c chan int) {
count := 0
for _, numb := range numbers {
count += numb
}
c <- count
}
func main() {
s := []int{1,2,3,4,5,6}
t := []int{10,20,30,40,50,60}
chan1 := make(chan int)
chan2 := make(chan int)
go sum(s, chan1)
go sum(t, chan2)
x:= <-chan1
y:= <-chan2
fmt.Println(x,y)
}
Çıktı:
21 210
map
map, aslında key-value şeklinde verilerin tutulmasını sağlayan bir veri yapısı gibi düşünebiliriz. “make” fonksiyonu ile oluşturulur. map değişkeni oluşturulurken herhangi bir büyüklük belirtmeye gerek yoktur. Veri eklendikçe otomatik olarak büyür. Eklendiği sırada bir sıralama oluşturmaz. İlgili map değişkenini bir döngüde verileri yazdırmak istediğinizde, her defasında farklı bir sırada olduğunu gözlemlersiniz.
Verinin fazla olduğu map array’lerinde, arama çok hızlı yapılabilmektedir. Bunun nedeni Go tasarımcılarının map’i unsafe olarak bırakmalarıdır. Oluşturulan global bir map’e aynı anda birden fazla mikro servisin yazma işlemi sırasında programınız crash olabilir. Mutex ile bu sorunu çözmeniz gerekecektir. Ancak aynı anda erişim söz konusu olmadığında mutex’e gerek yoktur. Dolayısıyla daha hızlı bir erişim sağlar.
package main
import "fmt"
type People struct {
IdentityNu string
Sex string
Nationality string
Likes []string
}
var w map[string]*People
func main() {
w= make(map[string]*People)
w["PartaNetworks"] = &People{IdentityNu:"11111111111",Sex:"man",Nationality:"Turkey",Likes:[]string{"Football","Basketball","Chess"}}
fmt.Println(w["PartaNetworks"].IdentityNu)
fmt.Println(w["PartaNetworks"].Sex)
fmt.Println(w["PartaNetworks"].Nationality)
fmt.Println(w["PartaNetworks"].Likes)
}
Çıktı:
11111111111
man
Turkey
[Football Basketball Chess]
interface
Go jenerik (generics) değildir. Eğer Object-Oriented bir programalama dili kullandıysanız jenerik yapılara hakimsinizdir. Jenerik yapılar olmadığında type yazımı biraz sizi zorlayabilir. Bu durumu interface{} ile biraz da olsa aşabilirsiniz.
package main
import "fmt"
type Food interface {
Cook() bool
Mix() bool
Eat() bool
}
type Meat struct {
name string
cookTime int
}
func (m Meat) Cook() bool {
fmt.Printf("Food %s is started. It will be finished after %d seconds.\n",m.name,m.cookTime)
return true
}
func (m Meat) Mix() bool {
fmt.Printf("Food %s is being mixed.\n",m.name)
return true
}
func (m Meat) Eat() bool{
fmt.Printf("Food %s started to be eaten.\n",m.name)
return true
}
func main() {
var m *Meat
m = &Meat{name:"Meatball",cookTime:100}
m.Cook()
m.Mix()
m.Eat()
fmt.Println("All is ok!")
}
Çıktı:
Food Meatball is started. It will be finished after 100 seconds.
Food Meatball is being mixed.
Food Meatball started to be eaten.
All is ok!
break
“break” devam eden işleyişi durdurur. Eğer döngü içerisinde belirtilmiş ise döngüden çıkış yapar. Switch/case yapısında belirtilmiş ise ilgili durumdan(case) çıkış yapar.
package main
import "fmt"
func main() {
var words = []string{"TR","EN","EU","GR"}
for _, word := range words {
if(word=="TR"){
fmt.Println("Word "+word+" found.")
break
}
}
}
Çıktı:
Word TR found.
continue
Bir loop içerisinde tanımlandığında “continue” satırının akabinde gelen satırlar çalıştırılmaz. Döngüye bir sonraki değerden devam ederek çalışır.
package main
import "fmt"
func main() {
var words = []string{"TR","EN","EU","GR"}
for _, word := range words {
if(word!="TR"){
continue
}
fmt.Println("Word "+word+" found.")
}
}
Çıktı:
Word TR found.
switch/case/fallthrough/default/select
package main
import (
"fmt"
"time"
)
func main() {
today := time.Now()
switch today.Day() {
case 5:
fmt.Println("Watch the film.")
break
case 10:
fmt.Println("Go to the gym.")
fallthrough
case 15:
fmt.Println("Watch the football match")
break
case 25:
fmt.Println("Eat some fruit.")
break
default:
fmt.Println("No information for this day.")
}
}
Çıktı:
Go to the gym.
Watch the football match
for/range
Aynı diğer dillerde olduğu gibi döngü için “for” anahtarını kullanırız. Döngü için while gibi bir seçenek yok. “for” ile her çeşit döngüyü oluşturabilirsiniz.
package main
import "fmt"
type People struct {
IdentityNu string
Sex string
Nationality string
Likes []string
}
var w map[string]*People
func main() {
w= make(map[string]*People)
w["Jack"] = &People{IdentityNu:"11111111111",Sex:"man",Nationality:"Turkey",Likes:[]string{"Football","Basketball","Chess"}}
w["Joe"] = &People{IdentityNu:"2222222222",Sex:"man",Nationality:"England",Likes:[]string{"Football","Swimming","Chess"}}
for name, p := range w{
fmt.Println(name+" is a "+p.Sex)
}
}
Çıktı:
Jack is a man
Joe is a man
if/else
Koşula göre seçim yapar. “if” koşulu desteklerse ilgili alana, desteklemezse “else” kısmındaki koda girer.
package main
import (
"fmt"
)
func main() {
var number = 56
if number%2 == 0 {
fmt.Printf("%d is even",number)
} else {
fmt.Printf("%d is odd",number)
}
}
Çıktı:
56 is even
goto
goto anahtarının kullanımının faydası konusunda pek çok tartışma olmuştur. Zamanla Yüksek Seviyeli Dillerden (High Level Programming Language) uzaklaştıkça GOTO kullanımının kodu karmaşıklaştırdığı ve sonrasında da spagetti koda sebep olduğu düşünülüyor (Bkz: https://homepages.cwi.nl/~storm/teaching/reader/Dijkstra68.pdf).
goto ilk olarak Assembly (Makine Kodu) de karşımıza çıkmaktadır. goto yerine kullanılabilecek pek çok anahtar vardır.
package main
import "fmt"
func main() {
var numb int = 90
LOOP: for numb < 100 {
if numb == 15 {
numb = numb + 1
goto LOOP
}
fmt.Printf("value of number: %d\n", numb)
numb++
}
}
Çıktı:
value of number: 90
value of number: 91
value of number: 92
value of number: 93
value of number: 94
value of number: 95
value of number: 96
value of number: 97
value of number: 98
value of number: 99
return
İşleyişin devam ettiği durumdan çıkış yapmak için kullanılan bir anahtar kelimedir. Bir fonksiyondan değer döndürmek için kullanılır.
package main
import (
"fmt"
"strings"
)
// A function that sum all elements in array
func Search(searchstr string) ([]string,bool){
var foundTeams []string
var found bool
for _,team :=range teams {
if(strings.HasPrefix(team,searchstr)){
foundTeams=append(foundTeams,team)
found = true
}
}
return foundTeams,found
}
var teams = []string{"Real Madrid","Real Zaragoza","Barcelona"}
func main() {
foundStr,foundBool:=Search("Real")
fmt.Println(foundStr)
fmt.Println(foundBool)
}
Çıktı:
[Real Madrid Real Zaragoza]
true
go
Eşzamanlılık, birbirinden bağımsız çalışmaların bir araya gelmesi ve kullanılmasıdır. Paralellik ile çoğu zaman karıştırılır. Metotlar/Fonksiyonlar, “go” kelimesi ile işleyişten bağımsız olarak çalışmaya devam eder. goroutine kesinlikle bir thread değildir.
Eşzamanlılık, bir paralellik değildir.
package main
import (
"fmt"
"time"
)
func routine(from string) {
for i := 0; i < 3; i++ {
fmt.Println(from, i)
}
}
func main() {
routine("call direct")
go routine("call goroutine")
go func(msg string) {
fmt.Println(msg)
}("going")
time.Sleep(time.Second)
fmt.Println("done")
}
Çıktı:
call direct 0
call direct 1
call direct 2
call goroutine 0
call goroutine 1
going
call goroutine 2
done
defer
Kendisini çevreleyen fonksiyon tamamen bitene kadar defer satırında çağırılan fonksiyonun çalışmasını erteler.
package main
import (
"fmt"
"os"
)
var f *os.File
func main() {
f = Create("/tmp/defer.txt")
defer Close()
Write()
}
func Create(p string) *os.File {
fmt.Println("creating")
f, err := os.Create(p)
if err != nil {
panic(err)
}
return f
}
func Write() {
fmt.Println("writing")
fmt.Fprintln(f, "data")
}
func Close() {
fmt.Println("closing")
err := f.Close()
if err != nil {
fmt.Fprintf(os.Stderr, "error: %v\n", err)
os.Exit(1)
}
}
Çıktı:
creating
writing
closing
GOPHER
Go projesine başlandığında ikonik bir maskot ya da logoya ihtiyaç vardı. Renee French bunu çizmek için gönüllü oldu. 2009 yılındaki lansman sırasında “Gopher” yani yer sincabı maskot olarak gösterilmesini önerdi. Ve “Go Gopher” doğmuş oldu. Tüm “Gopher” çizimlerini https://golang.org/doc/gopher/ sayfasından erişebilirsiniz.

Go Dünyada Nerede ?


KAYNAKLAR:
https://9p.io/sources/contrib/ericvh/go-plan9/doc/go_talk-20091030.pdf
https://venkatarangan.com/blog/2020/07/the-top-programming-languages-in-2020-by-ieee-spectrum/
https://flyaps.com/blog/top-10-coding-languages-used-by-global-companies/
Yorum yazabilmek için oturum açmanız gerekir.