Go 101
Go, Google tarafından geliştirilen, sadeliği, performansı ve güçlü concurrency desteğiyle öne çıkan açık kaynaklı bir programlama dilidir…
Go 101
Go, Google tarafından geliştirilen, sadeliği, performansı ve güçlü concurrency desteğiyle öne çıkan açık kaynaklı bir programlama dilidir. 2009 yılında duyurulan Go; özellikle backend geliştirme, web servisleri, API’ler, mikroservisler, cloud altyapıları ve sistem programlama gibi alanlarda kullanılmaktadır.

GoLang logo
Bu yazımda size Go diline nasıl giriş yapabileceğinizden ve temel kod parçalarından bahsedeceğim.
Klasik bir Go şablonu aşağıdaki gibidir:
package main
import "fmt"
func main() {
fmt.Println("Hello, World!")
}
Yukarıdaki kodda aklınıza takılan bazı şeyler olabilir. Mesela “package main nedir?”, “fmt’yi neden import ediyoruz?”, “func main() ne işe yarıyor?” veya “Neden bazı satırların sonunda ; yok?" gibi.
Tüm bu sorulara aşağıda cevap bulabileceksiniz.
package main nedir?
İlk olarak kodumuzun en üstünde yer alan package main ifadesiyle başlayalım.
Go’da her .go dosyası bir package'a ait olmak zorundadır. Package'lar, kodu organize etmek ve birbiriyle ilişkili kodları bir arada tutmak için kullanılır.
Buradaki main ise özel bir package ismidir. Bir Go programını çalıştırılabilir bir uygulama olarak oluşturmak istiyorsak programın giriş noktası main package'ının içerisindeki main fonksiyonudur.
Yani aşağıdaki iki ifade birbirinden farklı kavramları temsil eder:
package main
func main() {
// Programın çalışmaya başladığı nokta
}
Burada:
package main→ Dosyanınmainpackage'ına ait olduğunu belirtir.func main()→ Programın başlangıç noktasıdır.
Peki Go’da her zaman package main olmak zorunda mı?
Hayır.
Go’da farklı amaçlar için farklı package’lar oluşturabiliriz. Örneğin kullanıcı işlemlerini yöneten user isimli bir package oluşturabiliriz:
package user
type User struct {
Name string
}
Yukarıdaki durumda dosyamız user package'ına aittir. main package'ından farklı olarak burada main() fonksiyonuna ihtiyacımız yoktur.
Dolayısıyla önemli ayrım şu:
*package main, çalıştırılabilir bir Go programının package'ıdır.func main(), programın çalışmaya başladığı giriş noktasıdır.*
import "fmt" neden var?
İlk kodumuzda yer alan import "fmt" ifadesini fark etmişsinizdir.
Burada Go’nun import keyword'ünü kullanıyoruz.
Bir package içerisinde bulunan fonksiyonları, tipleri veya diğer öğeleri kullanabilmek için ilgili package’ı import etmemiz gerekir.
Peki fmt nedir?
fmt, Go'nun standart kütüphanesinde bulunan package'lardan biridir. Temel olarak formatlı input/output işlemleri için kullanılır.
Bizim örneğimizde ise terminale yazı yazdırmak için fmt package'ını kullanıyoruz:
fmt.Println("Hello, World!")
Buradaki yapıyı parçalarsak:
fmt → kullandığımız package
. → package içerisindeki bir öğeye erişim
Println → çağırdığımız fonksiyon
Yani bu ifade kısaca:
*“fmtpackage'ının içerisindekiPrintlnfonksiyonunu çağır."*
anlamına gelir.
Neden fmt'yi import etmek zorundayız?
Çünkü Println bizim yazdığımız bir fonksiyon değil. Go'nun standart kütüphanesinde bulunan fmt package'ının içerisinde yer alıyor.
Örneğin:
package main
func main() {
Println("Hello, World!")
}
şeklinde yazarsak Go, Println fonksiyonunun ne olduğunu bilemez ve hata verir.
Doğru kullanım:
package main
import "fmt"
func main() {
fmt.Println("Hello, World!")
}
Burada ayrıca Go’nun önemli bir kuralıyla karşılaşıyoruz:
Import ettiğimiz bir package’ı kullanmak zorundayız.
Örneğin:
package main
import "fmt"
func main() {
}
kodunu çalıştırdığımızda Go hata verecektir. Çünkü fmt import edilmiş olmasına rağmen kullanılmamıştır.
Go, kullanılmayan import’lara izin vermez. Bu yaklaşım ilk başta biraz katı görünse de kod içerisinde gereksiz import’ların birikmesini engeller.
func main() nedir?
Şimdi programımızın asıl giriş noktasına geldik:
func main() {
fmt.Println("Hello, World!")
}
Buradaki func, bir fonksiyon tanımladığımızı belirtir.
main ise fonksiyonun ismidir.
Parantezler:
()
fonksiyonun parametrelerini belirtmek için kullanılır. Bizim main fonksiyonumuz herhangi bir parametre almadığı için parantezlerin içi boştur.
Süslü parantezler ise:
{
...
}
fonksiyonun gövdesini belirtir.
Dolayısıyla:
func main() {
fmt.Println("Hello, World!")
}
ifadesini şu şekilde okuyabiliriz:
*“mainadında, parametre almayan bir fonksiyon tanımla ve içerisinde bulunan kodları çalıştır."*
Go programımız çalıştırıldığında main package'ının main fonksiyonu programın giriş noktası olarak çalıştırılır.
fmt.Println ne yapıyor?
Son olarak programımızın gerçekten iş yapan satırına bakalım:
fmt.Println("Hello, World!")
Println, verilen değerleri standart çıktıya yazdırır ve sonuna yeni satır ekler.
Örneğin:
fmt.Println("Hello")
fmt.Println("World")
çıktısı:
Hello
World
olacaktır.
Println dışında fmt package'ında sık kullanacağımız başka fonksiyonlar da vardır:
fmt.Print("Hello")
fmt.Println("Hello")
fmt.Printf("Hello %s", "World")
Print yeni satır eklemeden çıktı verir.
Println çıktının sonuna yeni satır ekler.
Printf ise belirli bir format kullanarak çıktı oluşturmamızı sağlar.
Örneğin:
name := "Ahmet"
fmt.Printf("Merhaba %s\n", name)
çıktısı:
Merhaba Ahmet
olacaktır.
Buradaki %s, string bir değer yerleştirmek için kullanılan format belirtecidir.
İlk Go programımızı artık okuyabiliriz
Şu ana kadar öğrendiklerimizle ilk programımıza tekrar bakalım:
package main
import "fmt"
func main() {
fmt.Println("Hello, World!")
}
Programımızın akışı kabaca şöyledir:
- Dosya
mainpackage'ına aittir. fmtpackage'ı kullanılmak üzere import edilir.- Programın giriş noktası olan
mainfonksiyonu tanımlanır. fmt.Printlnile terminaleHello, World!yazdırılır.
Birkaç satırlık basit bir kod gibi görünse de Go’nun temel çalışma mantığının önemli bir kısmını bu küçük örnekte görmüş olduk.
Şimdi biraz da Go’nun syntax kurallarına bakalım.
Go Syntax Kuralları
Bir programlama dilini öğrenirken sadece keyword’leri bilmek yeterli değildir. Dilin syntax kurallarını da bilmemiz gerekir.
Go bu konuda oldukça sade bir yapıya sahiptir. Ancak başka dillerden gelen geliştiricilerin dikkat etmesi gereken bazı farklılıklar bulunur.
Noktalı virgül ; kullanmak zorunda mıyız?
Go kodlarında çoğu zaman satırların sonunda ; görmeyiz.
Örneğin:
fmt.Println("Hello")
fmt.Println("World")
şeklinde yazabiliriz.
Java, C veya JavaScript gibi dillerde sıkça karşılaştığımız:
fmt.Println("Hello");
kullanımı Go’da genellikle gerekli değildir.
Go, belirli kurallara göre satır sonlarında semicolon’ları otomatik olarak ekler.
Bu nedenle günlük Go kodunda ; yazmayız.
{} kullanımı
Go’da süslü parantezler kod bloklarını belirtmek için kullanılır.
Örneğin:
if age >= 18 {
fmt.Println("Adult")
}
Burada { ifadesi koşula ait kod bloğunun başladığını belirtir.
Go’da dikkat edilmesi gereken önemli bir syntax kuralı vardır.
Aşağıdaki kullanım doğru değildir:
if age >= 18
{
fmt.Println("Adult")
}
Go’da { karakteri ilgili statement ile aynı satırda bulunmalıdır:
if age >= 18 {
fmt.Println("Adult")
}
Bu küçük bir detay gibi görünse de Go öğrenirken sık karşılaşabileceğiniz kurallardan biridir.
if içerisinde parantez kullanmalı mıyız?
Go’da if koşullarının etrafına parantez koymamıza gerek yoktur.
Örneğin:
if age >= 18 {
fmt.Println("Adult")
}
yeterlidir.
Şu kullanım ise Go’nun tercih ettiği syntax değildir:
if (age >= 18) {
fmt.Println("Adult")
}
Go’nun tasarımındaki temel fikirlerden biri gereksiz syntax’ı azaltmaktır.
Büyük ve küçük harf önemli mi?
Evet.
Go case-sensitive bir dildir.
Yani:
name
ile:
Name
aynı şey değildir.
Örneğin:
var name string
var Name string
iki farklı değişken tanımlar.
Ancak Go’da büyük ve küçük harf konusu sadece değişken isimleri açısından önemli değildir. Package’lar arasındaki erişim açısından da önemli bir anlam taşır.
Örneğin:
type User struct {
Name string
}
Buradaki Name büyük harfle başladığı için başka package'lardan erişilebilir.
Buna karşılık:
type User struct {
name string
}
şeklinde yazarsak name package dışından doğrudan erişilebilir olmaz.
Go’da bu konuya exported ve unexported kavramlarıyla ilerleyen bölümlerde daha detaylı değineceğiz.
Değişkenler
Artık kodumuzda veri tutmaya başlayabiliriz.
Go’da değişken tanımlamanın birkaç farklı yolu vardır.
En temel yöntem:
var name string = "Ahmet"
Burada:
var→ değişken tanımladığımızı belirtir.name→ değişkenin ismidir.string→ değişkenin tipidir."Ahmet"→ değişkene verdiğimiz değerdir.
Daha kısa bir kullanım da vardır:
var name = "Ahmet"
Burada Go, değere bakarak değişkenin tipini kendisi belirler.
Buna type inference denir.
Bir diğer ve Go’da oldukça sık kullanılan yöntem ise := operatörüdür:
name := "Ahmet"
Bu ifade:
var name string = "Ahmet"
ile benzer şekilde çalışır.
= ile := arasındaki fark nedir?
Bu ikisi yeni başlayanların en çok karıştırdığı konulardan biridir.
= mevcut bir değişkene değer atamak için kullanılır:
name := "Ahmet"
name = "Mehmet"
İlk satırda değişkeni oluşturduk.
İkinci satırda ise mevcut değişkenin değerini değiştirdik.
:= ise yeni bir değişken tanımlamak için kullanılır:
name := "Ahmet"
Bu nedenle:
name = "Ahmet"
ile:
name := "Ahmet"
aynı şey değildir.
:= kullanarak yeni bir değişken oluşturduğunuzda Go, değişkenin tipini sağ taraftaki değerden çıkarır.
:= her yerde kullanılabilir mi?
Hayır.
:= sadece bir fonksiyonun içerisinde yeni değişken tanımlarken kullanılabilir.
Örneğin:
func main() {
name := "Ahmet"
}
geçerlidir.
Ancak package seviyesinde:
package main
name := "Ahmet"
kullanımı geçerli değildir.
Package seviyesinde var kullanabiliriz:
package main
var name = "Ahmet"
Sabitler — const
Değeri program boyunca değişmemesi gereken durumlarda const kullanabiliriz.
Örneğin:
const pi = 3.14
Artık:
pi = 5
yapamayız.
Başka bir örnek:
const appName = "My Application"
Constant’lar özellikle program içerisinde değişmemesi gereken değerleri tanımlamak için kullanılır.
Temel Veri Tipleri
Go statik tipli bir dildir.
Yani bir değişkenin tipi belirlenir ve bu tip ile uyumlu değerler kullanılması beklenir.
En sık karşılaşacağımız temel veri tiplerinden bazıları şunlardır:
string
int
float64
bool
Örneğin:
var name string = "Ahmet"
var age int = 25
var price float64 = 99.99
var isActive bool = true
Burada:
string→ metinsel değerlerint→ tam sayılarfloat64→ ondalıklı sayılarbool→trueveyafalsedeğerleri
için kullanılır.
Tip sonradan değiştirilebilir mi?
Hayır.
Örneğin:
age := 25
age = "Ahmet"
kodumuz hata verecektir.
Çünkü age değişkeni oluşturulduğunda Go bunun int olduğunu belirlemiştir.
Bir int değişkene string değer atayamayız.
Bu durum Go’nun statik tip sisteminin bir sonucudur.
Fonksiyonlar
Kodumuzu tekrar kullanılabilir parçalara ayırmak için fonksiyonları kullanırız.
Basit bir fonksiyon:
func sayHello() {
fmt.Println("Hello")
}
Burada func keyword'ü bir fonksiyon tanımladığımızı belirtir.
Fonksiyonumuzu daha sonra çağırabiliriz:
func main() {
sayHello()
}
Çıktı:
Hello
Fonksiyon parametreleri
Fonksiyonlara dışarıdan veri gönderebiliriz.
Örneğin:
func sayHello(name string) {
fmt.Println("Hello", name)
}
Artık:
sayHello("Ahmet")
şeklinde çağırabiliriz.
Buradaki name string fonksiyonun bir parametre aldığını belirtir.
Fonksiyonlar değer döndürebilir
Fonksiyonlar sadece işlem yapmakla kalmaz, sonuç da döndürebilir.
Örneğin:
func add(a int, b int) int {
return a + b
}
Burada son taraftaki:
int
fonksiyonun int tipinde bir değer döndüreceğini belirtir.
Kullanımı:
result := add(10, 20)
fmt.Println(result)
çıktısı:
30
olacaktır.
Go’da aynı tipteki parametreleri daha kısa da yazabiliriz:
func add(a, b int) int {
return a + b
}
Bu iki kullanım aynıdır.
Birden Fazla Değer Döndürmek
Go’nun diğer birçok programlama dilinden ayrıldığı özelliklerden biri, fonksiyonların birden fazla değer döndürebilmesidir.
Örneğin:
func divide(a, b int) (int, int) {
return a / b, a % b
}
Bu fonksiyondan iki farklı değer döndürüyoruz.
Kullanımı:
result, remainder := divide(10, 3)
fmt.Println(result)
fmt.Println(remainder)
çıktısı:
3
1
şeklinde olacaktır.
Bu özellik özellikle Go’da error handling konusunda çok sık karşımıza çıkacaktır.
Koşullar — if
Programlarımızda belirli bir koşula göre farklı işlemler yapmak isteyebiliriz.
Bunun için if kullanılır:
age := 20
if age >= 18 {
fmt.Println("Adult")
}
Koşul doğruysa kod bloğu çalışır.
else ile alternatif bir durum belirleyebiliriz:
if age >= 18 {
fmt.Println("Adult")
} else {
fmt.Println("Minor")
}
Birden fazla koşul için else if kullanabiliriz:
if age >= 65 {
fmt.Println("Senior")
} else if age >= 18 {
fmt.Println("Adult")
} else {
fmt.Println("Minor")
}
Go’da while nerede?
Go öğrenirken bu soru oldukça sık sorulur.
C, Java veya Python gibi dillerde ayrı bir while yapısı bulunabilir.
Go’da ise ayrı bir while keyword'ü yoktur.
Bunun yerine for kullanılır.
Örneğin:
for age < 18 {
age++
}
Bu yapı while mantığıyla çalışır.
for Döngüsü
Go’da döngüler için for kullanılır.
Klasik kullanım:
for i := 0; i < 5; i++ {
fmt.Println(i)
}
Çıktı:
0
1
2
3
4
Burada:
i := 0
başlangıç değeridir.
i < 5
döngünün devam etme koşuludur.
i++
ise her iterasyondan sonra çalıştırılır.
Go’da sonsuz döngü de oluşturabiliriz:
for {
fmt.Println("Running...")
}
Bu döngüyü break ile sonlandırabiliriz:
for {
fmt.Println("Running...")
break
}
Array
Birden fazla aynı tipteki veriyi bir arada tutmak istediğimizde array kullanabiliriz.
Örneğin:
numbers := [3]int{10, 20, 30}
Buradaki:
[3]int
ifadesi 3 elemanlı bir int array'i olduğunu belirtir.
Elemanlara index üzerinden ulaşabiliriz:
fmt.Println(numbers[0])
fmt.Println(numbers[1])
fmt.Println(numbers[2])
Çıktı:
10
20
30
Go’da index’ler 0'dan başlar.
Slice
Go’da array ile birlikte çok sık kullanacağımız bir diğer yapı slice’tır.
Örneğin:
numbers := []int{10, 20, 30}
Burada array’den farklı olarak boyutu başlangıçta sabit bir yapı oluşturmuyoruz.
Yeni eleman ekleyebiliriz:
numbers = append(numbers, 40)
Artık:
[10 20 30 40]
değerine sahibiz.
Slice’lar Go’da oldukça sık kullanılır.
Array ve slice arasındaki temel farklardan biri, array’in uzunluğunun tipinin bir parçası olmasıdır:
[3]int
[5]int
bunlar farklı tiplerdir.
Slice ise:
[]int
şeklindedir ve dinamik olarak büyüyebilir.
Map
Bir key-value yapısına ihtiyaç duyduğumuzda map kullanabiliriz.
Örneğin:
users := map[string]int{
"Ahmet": 25,
"Mehmet": 30,
}
Burada:
string → key
int → value
olarak kullanılmıştır.
Veriye key üzerinden ulaşabiliriz:
fmt.Println(users["Ahmet"])
çıktısı:
25
Yeni bir değer eklemek de oldukça kolaydır:
users["Ayşe"] = 28
Artık map içerisinde Ayşe de bulunmaktadır.
Bir key’in map içerisinde olup olmadığını kontrol etmek için ise:
age, ok := users["Ahmet"]
if ok {
fmt.Println(age)
}
şeklinde bir kullanım görebiliriz.
Buradaki ok değeri, key'in bulunup bulunmadığını belirtir.
Struct
Go’da farklı veri tiplerini tek bir yapı altında toplamak için struct kullanabiliriz.
Örneğin bir kullanıcıyı temsil etmek istediğimizi düşünelim:
type User struct {
Name string
Age int
}
Burada User isimli yeni bir struct tipi oluşturduk.
Artık bir kullanıcı oluşturabiliriz:
user := User{
Name: "Ahmet",
Age: 25,
}
Değerlerine ise:
fmt.Println(user.Name)
fmt.Println(user.Age)
şeklinde ulaşabiliriz.
Struct’ları özellikle gerçek dünyadaki varlıkları kod içerisinde modellemek için sıkça kullanacağız.
Örneğin:
type Product struct {
Name string
Price float64
Stock int
}
gibi bir yapı oluşturabiliriz.
Method
Struct’lar ile birlikte method kavramıyla da karşılaşacağız.
Örneğin:
type User struct {
Name string
}
Bu struct’a ait bir method tanımlayabiliriz:
func (u User) SayHello() {
fmt.Println("Hello", u.Name)
}
Artık:
user := User{
Name: "Ahmet",
}
user.SayHello()
yazabiliriz.
Çıktı:
Hello Ahmet
Buradaki:
(u User)
kısmına receiver denir.
Bu sayede SayHello fonksiyonunun User tipine ait bir method olduğunu belirtmiş oluruz.
Pointer nedir?
Pointer konusu Go öğrenmeye başlayanlar için ilk başta biraz kafa karıştırıcı olabilir.
Temel olarak pointer, bir değerin bellekteki adresini tutmamızı sağlar.
Örneğin:
age := 25
ptr := &age
Buradaki &, age değişkeninin adresini almamızı sağlar.
Pointer’ın gösterdiği değere ise * ile ulaşabiliriz:
fmt.Println(*ptr)
çıktısı:
25
Pointer’lar özellikle bir fonksiyon içerisinde gönderilen değerin kendisini değiştirmek istediğimiz durumlarda karşımıza çıkar.
Örneğin:
func changeAge(age *int) {
*age = 30
}
Kullanımı:
age := 25
changeAge(&age)
fmt.Println(age)
çıktısı:
30
Burada fonksiyona age değişkeninin kendisini değil, bellekteki adresini gönderdik.
Pointer konusu bundan çok daha detaylıdır ancak başlangıç seviyesinde bilmemiz gereken temel mantık budur.
Error Handling
Go’nun en karakteristik özelliklerinden biri error handling yaklaşımıdır.
Birçok programlama dilinde hata yönetimi için try/catch gibi yapılar kullanılır.
Go’da ise hatalar genellikle fonksiyonlardan normal bir değer gibi döndürülür.
Örneğin:
result, err := doSomething()
if err != nil {
return err
}
Burada err bir hata olup olmadığını kontrol etmek için kullanılır.
Go’da error, özel bir interface'tir.
Bir fonksiyon hata oluşturabilecekse genellikle sonucu ve hatayı birlikte döndürür:
func divide(a, b int) (int, error) {
if b == 0 {
return 0, errors.New("cannot divide by zero")
}
return a / b, nil
}
Kullanımı:
result, err := divide(10, 0)
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println(result)
Burada:
if err != nil
ifadesini Go kodlarında çok sık göreceğiz.
nil kabaca "değer yok" anlamında düşünülebilir.
Dolayısıyla:
err != nil
ifadesi:
“Bir hata var mı?”
kontrolünü yapar.
Hata yoksa genellikle:
err == nil
olur.
Bu yaklaşım Go’da oldukça yaygındır:
result, err := someFunction()
if err != nil {
return err
}
İlk başta tekrar tekrar aynı yapıyı yazmak biraz fazla gelebilir. Ancak Go’nun error handling yaklaşımının temel amacı hataları açık ve kontrol edilebilir bir şekilde ele almaktır.
nil nedir?
nil, Go'da bazı tipler için "değer yok" durumunu temsil eder.
Örneğin pointer:
var ptr *int
fmt.Println(ptr)
değeri nil olabilir.
Benzer şekilde bazı durumlarda:
- pointer
- slice
- map
- function
- interface
- channel
gibi tiplerde nil kullanılabilir.
Ancak önemli bir nokta var: Her veri tipi nil alamaz.
Örneğin:
var age int = nil
geçerli değildir.
Çünkü int, nil alabilen bir tip değildir.
Package Yapısı
Başta package konusuna değinmiştik. Şimdi biraz daha gerçek bir proje yapısına bakalım.
Örneğin projemiz şu şekilde olabilir:
myproject/
├── go.mod
├── main.go
└── user/
└── user.go
main.go:
package main
import (
"fmt"
"myproject/user"
)
func main() {
u := user.User{
Name: "Ahmet",
}
fmt.Println(u.Name)
}
user/user.go:
package user
type User struct {
Name string
}
Burada main package'ı içerisinden user package'ını import ediyoruz.
Dikkat ederseniz User büyük harfle başlıyor:
type User struct
Bu önemli.
Go’da bir identifier büyük harfle başlıyorsa başka package’lar tarafından erişilebilir hale gelir.
Örneğin:
type User struct {
Name string
}
kullanılabilirken:
type user struct {
name string
}
package dışından doğrudan erişilebilir değildir.
Bu konu Go’da export mantığının temelini oluşturur.
Go Modules ve go.mod
Go projelerinde dependency yönetimi ve module bilgilerini go.mod dosyası üzerinden yönetiriz.
Yeni bir proje oluşturduğumuzda:
go mod init myproject
komutunu çalıştırabiliriz.
Bunun sonucunda:
go.mod
dosyası oluşur.
Basit bir go.mod dosyası şu şekilde görünebilir:
module myproject
go 1.24
Buradaki module, projenin module path'ini belirtir.
Go Modules konusu özellikle dışarıdan dependency eklemeye başladığımızda daha önemli hale gelir.
Go’nun Temel Komutları
Go ile çalışırken terminalde bazı komutları sürekli kullanacağız.
go run
Programı derleyip çalıştırmak için:
go run .
kullanabiliriz.
Örneğin:
go run main.go
şeklinde de çalıştırabiliriz.
go build
Programı derlemek için:
go build
kullanılır.
Bu komut kaynak kodumuzu derleyerek çalıştırılabilir bir binary oluşturabilir.
go fmt
Go’nun en güzel özelliklerinden biri kod formatlama konusunda standart bir araç sunmasıdır.
go fmt
komutuyla Go kodumuzu standart formata göre düzenleyebiliriz.
Örneğin kodu şu şekilde yazmış olsak bile:
func main(){fmt.Println("Hello")}
gofmt bunu standart Go formatına dönüştürür:
func main() {
fmt.Println("Hello")
}
Bu nedenle Go projelerinde kod formatı konusunda çok fazla tartışma yaşamayız.
go test
Go’nun kendi içerisinde test framework’ü bulunur.
Testleri çalıştırmak için:
go test
veya proje içerisindeki tüm package’ları test etmek için:
go test ./...
kullanabiliriz.
Test konusu bu yazının kapsamının dışında olduğu için burada sadece temel komutu bilmemiz yeterli.
go mod tidy
Projedeki dependency’leri düzenlemek için:
go mod tidy
komutunu kullanabiliriz.
Kullanılmayan dependency’leri temizler ve gerekli dependency bilgilerini go.mod ve go.sum dosyalarına göre düzenler.
Sonuç
Bu yazıda Go ile ilk karşılaştığımız kodun aslında ne anlama geldiğini adım adım incelemeye çalıştık.
Başlangıçta sadece birkaç satırdan oluşan şu kod vardı:
package main
import "fmt"
func main() {
fmt.Println("Hello, World!")
}
Ancak bu birkaç satırın içerisinde bile Go’nun temel yapı taşlarının önemli bir kısmı bulunuyor.
Artık:
package mainnedir,packagene işe yarar,importneden kullanılır,fmtnedir,fmt.Printlnne yapar,func main()nedir,- Go’da syntax kuralları nasıldır,
varve:=arasındaki fark nedir,constne işe yarar,- temel veri tipleri nelerdir,
- fonksiyonlar nasıl tanımlanır,
- fonksiyonlar nasıl değer döndürür,
ifvefornasıl kullanılır,- array ve slice arasındaki temel fark nedir,
- map nedir,
- struct ve method nedir,
- pointer’ın temel mantığı nedir,
- Go’da error handling nasıl yapılır,
- package’lar nasıl organize edilir,
- Go Modules nedir,
- temel
gokomutları nelerdir
gibi soruların cevaplarını biliyoruz.
Fakat Go’nun asıl güçlü taraflarından henüz bahsetmedik.
Go’yu backend ve cloud dünyasında bu kadar popüler yapan konuların başında goroutine, channel ve concurrency modeli geliyor.
Bir sonraki yazıda Go’nun en çok konuşulan özelliklerinden biri olan concurrency konusuna geçerek goroutine ve channelyapılarını inceleyeceğiz.
Go 101 serisinin bir sonraki bölümü olursa orada görüşmek üzere :)
메타데이터
- post_id
- 51db4e27d142
- slug
- go-101-51db4e27d142
- url
- https://medium.com/@ahmet.balcik.official/go-101-51db4e27d142
- canonical_url
- https://medium.com/@ahmet.balcik.official/go-101-51db4e27d142
- author_url
- https://medium.com/@ahmet.balcik.official
- status
- ok
- fetched_at
- 2026-08-23 03:47:58