Go: Java/Python Geliştiricileri için Temel Bilgiler 2026

Java veya Python deneyiminden yararlanarak Go'yu hızla öğrenin. Goroutine'ler, channel'lar, interface'ler ve sorunsuz bir geçiş için temel kalıplar.

Java ve Python geliştiricileri için Go rehberi

Go (veya Golang), mikro hizmetler, CLI araçları ve dağıtık sistemler için tercih edilen dil olarak yerini sağlamlaştırmıştır. 2009 yılında Google tarafından geliştirilen Go, Python'un sadeliğini C seviyesindeki performansla birleştirir. Java veya Python'dan gelen geliştiriciler için Go'ya geçiş, temel kavramlar oturduktan sonra şaşırtıcı derecede sorunsuz olur.

2026'da neden Go?

Go; Docker, Kubernetes, Terraform ve sayısız bulut altyapısının temelini oluşturur. Hızlı derleme, yerel eşzamanlılık desteği ve tek ikili dosya olarak dağıtım, Go'yu modern backend geliştirme için ideal kılar.

Go'yu kurma ve yapılandırma

Go'yu kurmak basit ve tüm platformlarda tutarlıdır. go aracı derleme, bağımlılık yönetimi ve test işlemlerini yönetir.

bash
# install.sh
# Installation on macOS with Homebrew
brew install go

# Installation on Linux (Ubuntu/Debian)
sudo apt update && sudo apt install golang-go

# Verify installation
go version
# go version go1.22.0 linux/amd64

Go proje yapısı katı ama basit kurallara uyar. go.mod dosyası modülü ve bağımlılıklarını tanımlar.

bash
# project-setup.sh
# Create a new project
mkdir my-project && cd my-project
go mod init github.com/user/my-project

# Generated structure:
# my-project/
# ├── go.mod    # Module manifest
# └── main.go   # Entry point

# Essential commands
go build          # Compile the project
go run main.go    # Compile and execute
go test ./...     # Run all tests
go fmt ./...      # Format code automatically

İlk Go programı

Aşağıda Go'nun temel söz dizimini gösteren basit bir program bulunmaktadır. Java ve Python ile karşılaştırma, farklılıkları görselleştirmeye yardımcı olur.

main.gogo
package main

import "fmt"

// Program entry point
func main() {
    // Declaration with type inference
    message := "Hello, Go!"
    fmt.Println(message)

    // Explicit declaration
    var count int = 42
    fmt.Printf("Count: %d\n", count)
}

Hemen göze çarpan özellikler: noktalı virgül yok, koşulların etrafında parantez yok ve := ile tür çıkarımı. Go, okunabilirlikten ödün vermeden sadeliğe öncelik verir.

Değişkenler ve temel türler

Go statik tiplidir ancak mükemmel tür çıkarımı sunar. Temel türler, kullanım senaryolarının çoğunu kapsar.

types.gogo
package main

import "fmt"

func main() {
    // Short declaration (inside functions only)
    name := "Alice"        // string
    age := 30              // int
    height := 1.75         // float64
    active := true         // bool

    // Explicit declaration
    var score int = 100
    var rate float64 = 3.14

    // Multiple declaration
    var (
        firstName string = "Bob"
        lastName  string = "Smith"
        points    int    = 0
    )

    // Zero values (default values)
    var count int      // 0
    var text string    // "" (empty string)
    var flag bool      // false
    var ptr *int       // nil

    fmt.Println(name, age, height, active)
}
Go'da sıfır değerler

Java veya Python'dan farklı olarak Go, değişkenleri otomatik olarak "sıfır değerleri" ile başlatır: sayılar için 0, string'ler için "", bool'lar için false, pointer ve slice'lar için nil.

Fonksiyonlar ve çoklu dönüş değerleri

Go birden fazla değer döndürmeye izin verir — hata yönetimi için yoğun şekilde kullanılan bir özellik.

functions.gogo
package main

import (
    "errors"
    "fmt"
)

// Simple function with typed parameters
func add(a, b int) int {
    return a + b
}

// Multiple returns (idiomatic pattern for errors)
func divide(a, b float64) (float64, error) {
    if b == 0 {
        return 0, errors.New("division by zero")
    }
    return a / b, nil
}

// Named returns
func getUser(id int) (name string, age int, err error) {
    if id <= 0 {
        err = errors.New("invalid ID")
        return
    }
    name = "Alice"
    age = 30
    return
}

// Variadic function
func sum(numbers ...int) int {
    total := 0
    for _, n := range numbers {
        total += n
    }
    return total
}

func main() {
    // Simple call
    result := add(5, 3)
    fmt.Println("5 + 3 =", result)

    // Explicit error handling
    quotient, err := divide(10, 3)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    fmt.Printf("10 / 3 = %.2f\n", quotient)

    // Ignore a returned value with _
    name, _, _ := getUser(1)
    fmt.Println("User:", name)

    // Variadic call
    total := sum(1, 2, 3, 4, 5)
    fmt.Println("Sum:", total)
}

Struct'lar ve metotlar

Struct'lar, Go'da özel türler oluşturmanın temel yapı taşlarıdır. Metotlar, receiver'lar aracılığıyla türlere bağlanır.

structs.gogo
package main

import "fmt"

// Struct definition
type User struct {
    ID       int
    Username string
    Email    string
    Active   bool
}

// Constructor (convention: NewTypeName)
func NewUser(id int, username, email string) *User {
    return &User{
        ID:       id,
        Username: username,
        Email:    email,
        Active:   true,
    }
}

// Method with value receiver (copy)
func (u User) FullInfo() string {
    status := "inactive"
    if u.Active {
        status = "active"
    }
    return fmt.Sprintf("%s <%s> (%s)", u.Username, u.Email, status)
}

// Method with pointer receiver (modification possible)
func (u *User) Deactivate() {
    u.Active = false
}

// Method with pointer receiver for modification
func (u *User) UpdateEmail(newEmail string) {
    u.Email = newEmail
}

func main() {
    // Create with constructor
    user := NewUser(1, "alice", "alice@example.com")
    fmt.Println(user.FullInfo())

    // Modify via method
    user.Deactivate()
    fmt.Println(user.FullInfo())

    // Direct creation
    user2 := User{
        ID:       2,
        Username: "bob",
        Email:    "bob@example.com",
    }
    fmt.Println(user2.FullInfo())
}
Value vs Pointer Receiver

Metot durumu değiştirdiğinde veya struct büyük olduğunda pointer receiver (*User) kullanılır. Hafif struct'larda salt okunur metotlar için value receiver (User) tercih edilir.

Interface'ler: örtük polimorfizm

Go interface'leri örtük olarak uygulanır. Bir tür, tüm metotlarını uyguluyorsa, açık bir bildirim olmadan interface'i karşılar.

interfaces.gogo
package main

import (
    "fmt"
    "math"
)

// Interface definition
type Shape interface {
    Area() float64
    Perimeter() float64
}

// Rectangle implements Shape implicitly
type Rectangle struct {
    Width, Height float64
}

func (r Rectangle) Area() float64 {
    return r.Width * r.Height
}

func (r Rectangle) Perimeter() float64 {
    return 2 * (r.Width + r.Height)
}

// Circle also implements Shape
type Circle struct {
    Radius float64
}

func (c Circle) Area() float64 {
    return math.Pi * c.Radius * c.Radius
}

func (c Circle) Perimeter() float64 {
    return 2 * math.Pi * c.Radius
}

// Function accepting the interface
func PrintShapeInfo(s Shape) {
    fmt.Printf("Area: %.2f, Perimeter: %.2f\n", s.Area(), s.Perimeter())
}

func main() {
    rect := Rectangle{Width: 10, Height: 5}
    circle := Circle{Radius: 7}

    // Polymorphism via interface
    PrintShapeInfo(rect)
    PrintShapeInfo(circle)

    // Slice of interfaces
    shapes := []Shape{rect, circle}
    for _, shape := range shapes {
        PrintShapeInfo(shape)
    }
}

Bu yaklaşım, implements anahtar kelimesinin zorunlu olduğu Java'dan köklü biçimde farklıdır. Go'da uyumluluk yapısal olup nominal değildir.

Go mülakatlarında başarılı olmaya hazır mısın?

İnteraktif simülatörler, flashcards ve teknik testlerle pratik yap.

Slice ve map: dinamik koleksiyonlar

Slice'lar diziler üzerinde dinamik görünümlerdir ve map'ler yerel hash tablolarıdır.

collections.gogo
package main

import "fmt"

func main() {
    // Slice: dynamic array
    numbers := []int{1, 2, 3, 4, 5}

    // Append elements
    numbers = append(numbers, 6, 7)

    // Slicing (similar to Python)
    subset := numbers[1:4]  // [2, 3, 4]
    fmt.Println("Subset:", subset)

    // Create slice with make
    scores := make([]int, 0, 10)  // len=0, cap=10
    scores = append(scores, 100, 95, 88)

    // Iteration with range
    for index, value := range numbers {
        fmt.Printf("numbers[%d] = %d\n", index, value)
    }

    // Map: hash table
    users := map[string]int{
        "alice": 30,
        "bob":   25,
    }

    // Add/Update
    users["charlie"] = 35

    // Check existence
    age, exists := users["alice"]
    if exists {
        fmt.Println("Alice's age:", age)
    }

    // Delete
    delete(users, "bob")

    // Map iteration
    for name, age := range users {
        fmt.Printf("%s is %d years old\n", name, age)
    }
}

İdiomatik hata yönetimi

Go'da istisna mekanizması bulunmaz. Hatalar, açıkça döndürülen değerlerdir ve titiz bir işleme zorunlu kılar.

errors.gogo
package main

import (
    "errors"
    "fmt"
    "os"
)

// Sentinel error (for comparison)
var ErrNotFound = errors.New("resource not found")
var ErrInvalidInput = errors.New("invalid input")

// Custom error with context
type ValidationError struct {
    Field   string
    Message string
}

func (e *ValidationError) Error() string {
    return fmt.Sprintf("validation failed on %s: %s", e.Field, e.Message)
}

// Function returning different error types
func GetUser(id int) (string, error) {
    if id <= 0 {
        return "", &ValidationError{
            Field:   "id",
            Message: "must be positive",
        }
    }
    if id > 1000 {
        return "", ErrNotFound
    }
    return "Alice", nil
}

// Error wrapping (Go 1.13+)
func ReadConfig(path string) ([]byte, error) {
    data, err := os.ReadFile(path)
    if err != nil {
        return nil, fmt.Errorf("reading config %s: %w", path, err)
    }
    return data, nil
}

func main() {
    // Basic pattern
    user, err := GetUser(-1)
    if err != nil {
        fmt.Println("Error:", err)

        // Type assertion for custom error
        var valErr *ValidationError
        if errors.As(err, &valErr) {
            fmt.Printf("Field: %s\n", valErr.Field)
        }

        // Comparison with sentinel error
        if errors.Is(err, ErrNotFound) {
            fmt.Println("User not found")
        }
    } else {
        fmt.Println("User:", user)
    }
}
errors.Is ve errors.As

Go 1.13'ten bu yana sentinel hatalarla karşılaştırmak için errors.Is() ve sarmalanmış bir hata zincirinden belirli bir hata türü çıkarmak için errors.As() kullanılır.

Goroutine'ler: hafif eşzamanlılık

Goroutine'ler, Go çalışma zamanı tarafından yönetilen hafif iş parçacıklarıdır. Bir goroutine başlatmak yalnızca birkaç KB bellek kullanır.

goroutines.gogo
package main

import (
    "fmt"
    "sync"
    "time"
)

func worker(id int, wg *sync.WaitGroup) {
    defer wg.Done()  // Decrement counter when done

    fmt.Printf("Worker %d starting\n", id)
    time.Sleep(time.Second)
    fmt.Printf("Worker %d done\n", id)
}

func main() {
    var wg sync.WaitGroup

    // Launch 5 goroutines
    for i := 1; i <= 5; i++ {
        wg.Add(1)
        go worker(i, &wg)  // 'go' prefix launches the goroutine
    }

    // Wait for all goroutines to complete
    wg.Wait()
    fmt.Println("All workers completed")
}

sync.WaitGroup, birden fazla goroutine'in tamamlanmasını beklemeyi sağlar. Bu, Go'daki temel paralellik kalıbıdır.

Channel'lar: goroutine'ler arası iletişim

Channel'lar, goroutine'ler arasında iletişim için tipli kanallardır. Güvenli senkronizasyon ve veri alışverişi sağlarlar.

channels.gogo
package main

import (
    "fmt"
    "time"
)

func producer(ch chan<- int) {
    for i := 1; i <= 5; i++ {
        fmt.Println("Producing:", i)
        ch <- i  // Send on channel
        time.Sleep(100 * time.Millisecond)
    }
    close(ch)  // Close channel when done
}

func consumer(ch <-chan int, done chan<- bool) {
    for value := range ch {  // Iterate until closed
        fmt.Println("Consuming:", value)
    }
    done <- true
}

func main() {
    ch := make(chan int)     // Unbuffered channel
    done := make(chan bool)

    go producer(ch)
    go consumer(ch, done)

    <-done  // Wait for consumer to finish
    fmt.Println("All done")
}

Tamponlu channel'lar ve select

channels_advanced.gogo
package main

import (
    "fmt"
    "time"
)

func main() {
    // Buffered channel (capacity 3)
    buffered := make(chan int, 3)
    buffered <- 1
    buffered <- 2
    buffered <- 3
    // buffered <- 4  // Would block since buffer is full

    fmt.Println(<-buffered)  // 1

    // Select: channel multiplexing
    ch1 := make(chan string)
    ch2 := make(chan string)

    go func() {
        time.Sleep(100 * time.Millisecond)
        ch1 <- "from ch1"
    }()

    go func() {
        time.Sleep(200 * time.Millisecond)
        ch2 <- "from ch2"
    }()

    // Wait for first available message
    for i := 0; i < 2; i++ {
        select {
        case msg1 := <-ch1:
            fmt.Println("Received:", msg1)
        case msg2 := <-ch2:
            fmt.Println("Received:", msg2)
        case <-time.After(500 * time.Millisecond):
            fmt.Println("Timeout!")
        }
    }
}
Go felsefesi: CSP

Go, CSP (Communicating Sequential Processes) modelini izler: "Bellek paylaşarak iletişim kurmayın; iletişim kurarak bellek paylaşın." Channel'lar yarış koşullarını önler.

Go'da test yazma

Go, minimalist ancak etkili bir test çerçevesi içerir. Test dosyaları _test.go ile biter.

calculator.gogo
package calculator

func Add(a, b int) int {
    return a + b
}

func Divide(a, b int) (int, error) {
    if b == 0 {
        return 0, errors.New("division by zero")
    }
    return a / b, nil
}
calculator_test.gogo
package calculator

import (
    "testing"
)

// Basic test
func TestAdd(t *testing.T) {
    result := Add(2, 3)
    expected := 5

    if result != expected {
        t.Errorf("Add(2, 3) = %d; want %d", result, expected)
    }
}

// Table-driven tests (recommended pattern)
func TestAddTableDriven(t *testing.T) {
    tests := []struct {
        name     string
        a, b     int
        expected int
    }{
        {"positive numbers", 2, 3, 5},
        {"negative numbers", -2, -3, -5},
        {"zero", 0, 0, 0},
        {"mixed", -5, 10, 5},
    }

    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            result := Add(tt.a, tt.b)
            if result != tt.expected {
                t.Errorf("Add(%d, %d) = %d; want %d",
                    tt.a, tt.b, result, tt.expected)
            }
        })
    }
}

// Error test
func TestDivideByZero(t *testing.T) {
    _, err := Divide(10, 0)
    if err == nil {
        t.Error("Expected error for division by zero")
    }
}

// Benchmark
func BenchmarkAdd(b *testing.B) {
    for i := 0; i < b.N; i++ {
        Add(100, 200)
    }
}

Testler go test ./... komutuyla, benchmark'lar ise go test -bench=. komutuyla çalıştırılır.

HTTP: minimalist web sunucusu

Go, standart kütüphanesiyle yüksek performanslı HTTP sunucuları oluşturmada öne çıkar.

server.gogo
package main

import (
    "encoding/json"
    "log"
    "net/http"
)

type User struct {
    ID   int    `json:"id"`
    Name string `json:"name"`
}

func main() {
    // Simple route
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte("Hello, Go!"))
    })

    // JSON route
    http.HandleFunc("/api/users", func(w http.ResponseWriter, r *http.Request) {
        users := []User{
            {ID: 1, Name: "Alice"},
            {ID: 2, Name: "Bob"},
        }

        w.Header().Set("Content-Type", "application/json")
        json.NewEncoder(w).Encode(users)
    })

    // Route with method
    http.HandleFunc("/api/user", func(w http.ResponseWriter, r *http.Request) {
        switch r.Method {
        case "GET":
            w.Write([]byte("Get user"))
        case "POST":
            w.Write([]byte("Create user"))
        default:
            http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
        }
    })

    log.Println("Server starting on :8080")
    log.Fatal(http.ListenAndServe(":8080", nil))
}

Bu sunucu, goroutine'ler sayesinde binlerce eşzamanlı bağlantıyı yönetir. Her istek otomatik olarak kendi goroutine'inde işlenir.

Sonuç

Go, backend geliştirmeye pragmatik bir yaklaşım sunar: basit söz dizimi, hızlı derleme, yerel eşzamanlılık ve mükemmel araçlar. Java veya Python geliştiricileri için geçiş, bazı farklı kuralların kabul edilmesini gerektirir (açık hata yönetimi, Go 1.18 öncesi sınırlı generics), ancak performans ve bakım kolaylığı açısından faydalar hemen kendini gösterir.

Başlangıç kontrol listesi

  • ✅ Go'yu resmi siteden veya paket yöneticisinden kurun
  • go build, go run, go test, go fmt komutlarında ustalaşın
  • ✅ Slice ve array arasındaki farkı anlayın
  • ✅ Hata yönetimi için if err != nil kalıbını benimseyin
  • ✅ Eşzamanlılık için goroutine'leri ve channel'ları kullanın
  • testing paketiyle table-driven testler yazın

Pratik yapmaya başla!

Mülakat simülatörleri ve teknik testlerle bilgini test et.

Go ekosistemi olgun durumdadır; web geliştirme için Gin, Echo ve Fiber gibi popüler framework'ler ve CLI'lar için Cobra gibi araçlar mevcuttur. Bu sağlam temeller üzerine, generics (Go 1.18+), context paketi ve eşzamanlılık kalıpları gibi ileri düzey konuları keşfetmek kolaylaşır.

Etiketler

#go
#golang
#concurrency
#goroutines
#backend

Paylaş

İlgili makaleler