Mert Özen Her Satırda Daha İleri
Backend Go ile Backend — #02

Go Kurulumu, Module'ler ve Proje Yapısı: go.mod, Package'lar, internal/ ve cmd/

Mert Özen 15 Kas 2026 13 dk 4 görüntülenme
Go Kurulumu, Module'ler ve Proje Yapısı: go.mod, Package'lar, internal/ ve cmd/

Go'da bir module go.mod ile tanımlanır: go satırı Go 1.21'den beri bağlayıcı bir minimum sürümdür, go.sum her bağımlılığın hash'ini tutar, indirmeler proxy.golang.org ve sum.golang.org üzerinden doğrulanır. go mod init'in yazdığı sürümün hikâyesi, toolchain satırı ve GOTOOLCHAIN, tool directive ile staticcheck, büyük harfle export, internal/ ve cmd/ yapısı, go work, go mod tidy -diff ve Go 1.27'de require bloklarının ikiye toplanması.

Sürüm notu: Bu yazıdaki kodlar Go 1.27.4 ile derlenip çalıştırılmıştır; module'ün go satırı 1.26.0'dır ve kod Go 1.26.11 ile de derlenir. Geliştirici aracı olarak staticcheck 2026.2.2 (module sürümü v0.8.2) kullanılmıştır.

Önce Tahmin Et

01'de sitedeki serilerin ortak örnek uygulaması Bookstore'un (bir online kitapçı) ilk Go servisini go mod init bookstore ile başlatmıştık. Oluşan go.mod dosyası iki satırdı:

module bookstore

go 1.27.4

Ekipten biri makinesinde hâlâ Go 1.26.11 kullanıyor ve şirketin build sunucusunda GOTOOLCHAIN=local ayarı var, yani Go başka bir toolchain indirmiyor. Bu kişi projeyi çekip go build ./... çalıştırınca ne olur? Kod 1.27'ye özgü hiçbir şey kullanmıyor; derlenir mi, uyarı mı verir, yoksa hiç başlamaz mı? Aynı kişi GOTOOLCHAIN ayarını varsayılan değerinde bıraksaydı ne değişirdi?

GOTOOLCHAIN=go1.26.11 go build ./...
go: go.mod requires go >= 1.27.4 (running go 1.26.11; GOTOOLCHAIN=go1.26.11)

Build hiç başlamadı. go satırı bir yorum ya da öneri değil, Go 1.21'den beri bağlayıcı bir minimum sürüm. Kod 1.26'da derlenebilecek olsa da go.mod 1.27.4 istiyor ve toolchain bu isteği reddediyor. Varsayılan ayarda ise Go, gereken toolchain'i kendisi indirip build'i onunla yapar. Bu yazıda go.mod'un her satırını, go.sum'ı ve module proxy'yi açıp tek dosyalık servisi cmd/ ve internal/ ile gerçek bir proje yapısına taşıyacağız.

Go'yu Kurmak

Go'nun resmî dağıtımı go.dev/dl adresinde. Windows için MSI (Microsoft Installer; Windows'un kurulum paketi biçimi) dosyasını indirip kurarsın; Go'yu C:\Program Files\Go altına koyar ve go komutunu PATH'e (işletim sisteminin komutları aradığı klasör listesi) ekler. İstersen aynı sayfadaki zip arşivini istediğin bir klasöre açıp bin klasörünü PATH'e kendin de ekleyebilirsin; ben bu yazıları hazırlarken arşiv dosyasını kullandım ve sayfada yazan SHA256 (dosyanın içeriğinden hesaplanan 256 bitlik hash) değeriyle indirdiğim dosyanın hash'ini karşılaştırdım. Kurulum bir SDK ile runtime'ı ayrı ayrı istemez, çünkü Go'da runtime her binary'nin içine girer.

Kurulumdan sonra bilmen gereken iki klasör var. Birincisi Go'nun kendisi (GOROOT). İkincisi GOPATH; varsayılan değeri Windows'ta %USERPROFILE%\go. İndirilen module'ler GOPATH\pkg\mod altındaki module cache'e, go install ile kurduğun araçlar GOPATH\bin altına gider. NuGet'in %USERPROFILE%\.nuget\packages klasörü ne işe yarıyorsa module cache de o işi yapar. Eski Go yazılarında projelerin GOPATH\src altında olması gerektiğini okuyabilirsin; module'ler geldikten sonra bu kural kalktı, projen diskin herhangi bir yerinde durabilir.

go.mod Satır Satır

module bookstore satırı module path'i tanımlar. Bu path, module içindeki package'ların import yollarının ön ekidir: internal/catalog klasöründeki package'ı bookstore/internal/catalog diye import edeceğiz. Başkalarının go get ile indireceği bir library yazıyorsan path, kodun durduğu yeri göstermelidir, örneğin github.com/kullanici/bookstore. Bizim gibi başka bir module'ün import etmeyeceği bir uygulamada kısa bir isim yeterli. C# tarafındaki Bookstore.Api projesinin assembly adını düşünebilirsin; fark, Go'da bu adın import yollarında her yerde görünmesi.

go satırı module'ün istediği en düşük Go sürümü. Önce Tahmin Et'te gördüğümüz gibi Go 1.21'den beri bağlayıcı: daha eski bir toolchain module'ü build etmeyi reddeder. Aynı satır dil sürümünü de seçer. Örneğin 1.22'de değişen döngü değişkeni davranışı, go satırı 1.22 ya da üzeri olan module'lerde geçerlidir; 03'te bunu göreceğiz. C#'taki LangVersion ile TargetFramework'ün tek satırda birleşmiş hâli gibi.

go mod init'in bu satıra ne yazdığının küçük bir hikâyesi var. Go 1.26.0, yeni module'lere bir önceki sürümü (go 1.25.0) yazmaya başlamıştı. Amaç, yeni açılan projelerin desteklenen iki sürümde de çalışmasıydı. Ama değişiklik şikâyet aldı ve 1.26.1'de geri alındı (Go issue #77653); 1.26 release notes'unda ise hâlâ ilk davranış yazıyor. Bugün 1.27.4 de kendi sürümünü yazıyor, 01'deki go 1.27.4 satırı bu yüzden. Seriyi 1.26'da da derlenecek şekilde yazdığımız için satırı kendimiz indiriyoruz:

go mod edit -go=1.26.0
module bookstore

go 1.26.0

toolchain satırı ise bir öneri: "bu module'ü geliştirirken şu toolchain'i kullan". Sadece build ettiğin module ana module ise ve elindeki toolchain önerilenden eskiyse devreye girer. GOTOOLCHAIN environment variable'ı da bu indirme davranışını yönetir. Varsayılan değeri Go'nun kendi klasöründeki go.env dosyasında yazıyor:

# Automatically download newer toolchains as directed by go.mod files.
# See https://go.dev/doc/toolchain for details.
GOTOOLCHAIN=auto

go 1.26.0 ve toolchain go1.27.4 satırları olan küçük bir module'de Go 1.26.11'in go komutunu iki ayarla çalıştırdım:

GOTOOLCHAIN=auto go env GOVERSION
GOTOOLCHAIN=local go env GOVERSION
go: downloading go1.27.4 (<goos>/<goarch>)
go1.27.4
go1.26.11

auto ayarında 1.26.11, toolchain satırını görüp 1.27.4'ü indirdi ve komutu onunla çalıştırdı. Parantez içinde senin platformun yazar, Windows x64'te windows/amd64. local ayarında ise kendi sürümüyle devam etti; go 1.26.0 isteğini zaten karşılıyordu. İndirilen toolchain de sıradan bir module gibi module cache'e girer ve checksum database'den doğrulanır. Bookstore'da toolchain satırı kullanmıyoruz; CI'daki Go sürümünü pipeline'da açıkça seçmek daha anlaşılır.

go.sum, Module Proxy ve Checksum Database

Projeye ilk bağımlılığı ekleyelim. Uygulama kodu şimdilik sadece standart kütüphaneyi kullanıyor, bu yüzden ilk bağımlılık bir geliştirici aracı olacak: Go topluluğunun en yaygın static analysis aracı staticcheck. Go 1.24'ten beri araçlar go.mod'a tool satırıyla eklenebiliyor; .NET'teki dotnet-tools.json ile local tool'ların karşılığı.

go get -tool honnef.co/go/tools/cmd/staticcheck@v0.8.2
go: downloading honnef.co/go/tools v0.8.2
go: downloading golang.org/x/tools v0.51.0
go: downloading github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c
go: downloading golang.org/x/exp/typeparams v0.0.0-20231108232855-2478ac86f678
go: downloading golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa
go: downloading golang.org/x/sync v0.23.0
go: downloading golang.org/x/mod v0.41.0
go: added github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c
go: added golang.org/x/exp/typeparams v0.0.0-20231108232855-2478ac86f678
go: added golang.org/x/mod v0.41.0
go: added golang.org/x/sync v0.23.0
go: added golang.org/x/tools v0.51.0
go: added honnef.co/go/tools v0.8.2
module bookstore

go 1.26.0

tool honnef.co/go/tools/cmd/staticcheck

require (
    github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c // indirect
    golang.org/x/exp/typeparams v0.0.0-20231108232855-2478ac86f678 // indirect
    golang.org/x/mod v0.41.0 // indirect
    golang.org/x/sync v0.23.0 // indirect
    golang.org/x/tools v0.51.0 // indirect
    honnef.co/go/tools v0.8.2 // indirect
)

require bloğu, build'de kullanılacak module'leri ve sürümlerini kesin olarak yazar. // indirect, o module'ü bizim kodumuzun doğrudan import etmediğini söyler; staticcheck de uygulama kodundan import edilmediği için indirect sayıldı. v1.4.1-0.20240526193622-a339e1f7089c gibi uzun sürümler pseudo-version: tag'lenmemiş bir commit'e verilen, tarihi ve commit hash'ini içeren sürüm. Artık aracı herkes aynı sürümle çalıştırır:

go tool staticcheck -version
go tool staticcheck ./...
staticcheck 2026.2.2 (0.8.2)

İkinci komut hiçbir şey yazmadı, yani bulgu yok. Aynı komutla birlikte bir go.sum dosyası da oluştu. İçinden iki satır:

honnef.co/go/tools v0.8.2 h1:+jPbCzuYxYrcoOvCecYUFDj+XJQRmzIhJmlbpps21Zk=
honnef.co/go/tools v0.8.2/go.mod h1:xG1Q4n+mg3bKZrO6RWFA9jFlkqplflmDRHGeuexiLDs=

Her module sürümü için iki hash var: biri module'ün bütün dosyalarının, diğeri sadece go.mod dosyasının. Go bir module'ü indirdiğinde hash'i hesaplar ve go.sum'daki değerle karşılaştırır; tutmazsa build durur. go.sum bir lock dosyası değil, sürümleri go.mod zaten kesin olarak yazıyor. Görevi, aynı sürümün her makinede birebir aynı içerik olduğunu garanti etmek. Bu yüzden ikisi de commit edilir.

Hash'in ilk kez nereden geldiği sorusunun cevabı checksum database. Module'ler varsayılan olarak doğrudan GitHub'dan değil, Google'ın işlettiği module proxy'den iner. Hash'ler de herkesin aynı listeyi gördüğü, sonradan değiştirilemeyen bir log'da tutulur:

go env GOPROXY GOSUMDB
https://proxy.golang.org,direct
sum.golang.org

Biri GitHub'daki bir tag'i silip aynı isimle farklı kod yayınlasa bile proxy ilk gördüğü içeriği vermeye devam eder, checksum database de farklı bir hash'i kabul etmez. NuGet'teki karşılıklarıyla düşünürsek: go.mod'daki require satırları PackageReference'ların, proxy nuget.org'un, go.sum ise packages.lock.json'daki content hash'lerin karşılığı. Şirket içindeki private module'ler için GOPRIVATE ayarı Go'ya bu module'leri proxy'ye ve checksum database'e sormamasını söyler. Module cache'teki dosyaların değişmediğini de şöyle kontrol edersin:

go mod verify
all modules verified

Son bir fark: Go, build'de hangi sürümün kullanılacağını go.mod dosyalarındaki minimum isteklerden seçer. Bu algoritmanın adı MVS (Minimal Version Selection; her module için istenen en yüksek minimum sürümü seçen kural). Bir bağımlılığın yeni sürümü yayınlandı diye senin build'in değişmez; sürüm ancak sen go get ile yükselttiğinde değişir.

Package = Klasör, Büyük Harf = Export

Şimdi tek dosyalık servisi bölelim. Go'da bir klasör bir package'tır; klasördeki bütün .go dosyaları aynı package adını taşır. Kitapları internal/catalog package'ına taşıyoruz. Bu package C#'taki Bookstore.Catalog namespace'inin karşılığı:

// Package catalog, Bookstore'un sattığı kitapları tutar.
package catalog

// Book, katalogdaki bir kitaptır.
type Book struct {
    ISBN  string `json:"isbn"`
    Title string `json:"title"`
}

// books export edilmiyor: diğer package'lar ona sadece Store üzerinden ulaşır.
var books = []Book{
    {ISBN: "9780441172719", Title: "Dune"},
    {ISBN: "9780547928227", Title: "The Hobbit"},
    {ISBN: "9780141439549", Title: "Middlemarch"},
}

// Store şimdilik kitapları bellekten verir.
type Store struct{}

// All, katalogdaki bütün kitapları döndürür.
func (Store) All() []Book {
    return books
}

Book, Store ve All büyük harfle başlıyor, yani export ediliyor; C#'taki public. books küçük harfle başlıyor ve sadece catalog package'ının içinden görünüyor. C#'ta internal erişimi assembly seviyesindeydi; Go'da küçük harfli isimlerin sınırı package. Yorumların ismin kendisiyle başlaması da bir Go kuralı: go doc ve linter'lar bu biçimi bekler. main.go artık cmd/bookstore-api klasöründe ve kitapları catalog'dan alıyor:

// bookstore-api komutu, Bookstore HTTP API'sini sunar.
package main

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

    "bookstore/internal/catalog"
)

func main() {
    var store catalog.Store

    http.HandleFunc("GET /hello", func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte("Hello from Bookstore API\n"))
    })
    http.HandleFunc("GET /api/books", func(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Content-Type", "application/json")
        json.NewEncoder(w).Encode(store.All())
    })

    addr := "127.0.0.1:52710"
    log.Printf("bookstore-api listening on http://%s", addr)
    log.Fatal(http.ListenAndServe(addr, nil))
}

var store catalog.Store satırı bir constructor çağırmıyor. Store boş bir struct ve zero value'su kullanıma hazır; zero value konusuna 03'te döneceğiz. Import grupları da gofmt'un sevdiği düzende: önce standart kütüphane, boş satır, sonra module içi package'lar. Bilerek küçük harfli books'a dışarıdan erişmeyi deneyelim, store.All() yerine catalog.books yazalım:

go build ./...
# bookstore/cmd/bookstore-api
cmd/bookstore-api/main.go:13:6: declared and not used: store
cmd/bookstore-api/main.go:20:37: name books not exported by package catalog

İki hata aldık. İkincisi beklediğimiz görünürlük hatası. Birincisi 01'de konuştuğumuz kural: store değişkeni artık kullanılmadığı için derleyici onu da hata saydı.

internal/ ve cmd/: Resmî Rehbere Göre Sade Bir Yapı

Projenin yeni hâli şöyle:

bookstore/
    go.mod
    go.sum
    cmd/
        bookstore-api/
            main.go
    internal/
        catalog/
            catalog.go

Bu yapı go.dev'deki "Organizing a Go module" rehberinin server projeleri için önerdiği yapı. Çalıştırılabilir programlar cmd/ altında, her biri kendi klasöründe durur; ileride bir veri aktarma aracı eklersek cmd/bookstore-import olur. Server mantığı ise internal/ altına girer. internal adı Go için özel: bu isimli bir klasörün altındaki package'ları sadece internal'ın bir üst klasöründen başlayan ağaçtaki kod import edebilir. Yani bookstore/internal/catalog'u bookstore module'ündeki herkes kullanabilir, başka bir module kullanamaz. C#'taki internal erişim belirleyicisinin package ağacı seviyesindeki karşılığı gibi; üstelik derleyici değil go komutu uygular.

İnternette "Go standard project layout" diye arayınca çıkan ilk sonuçlardan biri GitHub'daki golang-standards/project-layout deposu. Adına rağmen resmî bir standart değil; deponun README'si de bunu açıkça söylüyor ve Go ekibinden Russ Cox 2021'de depoda "bu standart bir Go proje yapısı değil" başlıklı bir issue açmıştı. O depodaki pkg/, api/, web/, build/ gibi klasörlerin çoğu küçük bir servis için gereksiz. Resmî rehberin yaklaşımı daha sade: ihtiyaç doğdukça klasör aç. Bu seride cmd/bookstore-api, internal/catalog ve 04'te ekleyeceğimiz internal/orders ile ilerleyeceğiz.

go work: Birden Fazla Module ile Aynı Anda Çalışmak

Bazen iki module'ü aynı anda geliştirirsin: bir library ve onu kullanan bir uygulama gibi. Library'yi her değişiklikte yayınlamak yerine Go 1.18'den beri bir workspace dosyası açabilirsin. internal kuralını da bu yolla deneyelim. bookstore klasörünün yanına example.com/reports adında ikinci bir module açtım ve main.go'suna bookstore/internal/catalog import'unu ekledim:

go work init ./bookstore ./reports
cat go.work
cd reports && go build ./...
go 1.27.4

use (
    ./bookstore
    ./reports
)
package example.com/reports
    main.go:6:2: use of internal package bookstore/internal/catalog not allowed

Workspace sayesinde reports module'ü bookstore'u yerel klasörden görüyor, ama internal kuralı yine geçerli. catalog'u başka module'lerle paylaşmak istersen onu internal dışına taşıman gerekir; bu da o package'ın API'sini artık geriye dönük uyumlu tutman gerektiği anlamına gelir. go.work genellikle commit edilmez; yerel geliştirme kolaylığıdır. Visual Studio'da iki projeyi aynı solution'a ekleyip ProjectReference vermenin geçici bir karşılığı gibi düşünebilirsin.

Bağımlılık Güncellemek ve go mod tidy

Günlük komutlar az: go get example.com/mod@v1.2.3 bir bağımlılığı ekler ya da belirli bir sürüme taşır, go get -u ./... kodun kullandığı bağımlılıkları yükseltir, go get example.com/mod@none kaldırır, go mod tidy ise go.mod ve go.sum'ı koda göre düzeltir: eksikleri ekler, kullanılmayanları siler. staticcheck'i ekledikten sonra go.sum'ın tidy olup olmadığını -diff ile sordum. Bu bayrak dosyaları değiştirmez, sadece farkı yazar ve fark varsa sıfırdan farklı bir exit code döner (çıktı kısaltılmış):

go mod tidy -diff
diff current/go.sum tidy/go.sum
--- current/go.sum
+++ tidy/go.sum
-golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ=
+github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
+github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
+golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM=
+golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY=

go get sadece build için gerekenleri yazmıştı; tidy bağımlılıkların kendi testleri için gereken hash'leri de ekliyor ve kullanılmayan bir satırı siliyor. go mod tidy'yi çalıştırıp dosyaları commit ettikten sonra aynı komut hiçbir şey yazmadı ve 0 döndü. Bu komut CI için iyi bir kontrol: biri go.mod'u güncellemeyi unutursa pipeline durur.

Go 1.27'de tidy'ye küçük ama faydalı bir davranış eklendi. Zamanla go.mod'da birden fazla require bloğu birikir; elle eklenen satırlar, farklı araçların açtığı bloklar. go satırı 1.27 ya da üzeri olan module'lerde tidy bunları en fazla iki bloğa toplar: biri doğrudan, biri indirect bağımlılıklar için. Dağınık bir go.mod ile denedim:

module example.com/tidydemo

go 1.27.0

require github.com/go-chi/chi/v5 v5.5.0

require golang.org/x/mod v0.41.0 // indirect

require (
    // kod analizi yardımcıları
    golang.org/x/tools v0.51.0
)

require golang.org/x/sync v0.23.0 // indirect
go mod tidy
cat go.mod
module example.com/tidydemo

go 1.27.0

require (
    github.com/go-chi/chi/v5 v5.5.0
    // kod analizi yardımcıları
    golang.org/x/tools v0.51.0
)

require (
    golang.org/x/mod v0.41.0 // indirect
    golang.org/x/sync v0.23.0 // indirect
)

Dört blok ikiye indi ve bağımlılığa bağlı yorum korundu. Aynı dosyayı go 1.26.0 ile denediğimde 1.27.4'ün tidy'si dört bloğu yerinde bıraktı; sadece tek satırlık parantezli bloğu, yorumu üstte kalacak şekilde tek satıra indirdi. Yani bu davranış toolchain sürümüne değil, module'ün go satırına bağlı. Bookstore go 1.26.0'da kaldığı için bizde devreye girmiyor; zaten tek bir require bloğumuz var.

Üretimde Dikkat

go.mod ve go.sum'ı her zaman birlikte commit et ve CI'da go mod tidy -diff ile go mod verify çalıştır. Build komutları varsayılan olarak go.mod'u değiştirmez; eksik bir satır varsa sessizce eklemek yerine hata verir. Bu iyi bir davranış, build sırasında bağımlılık listesi değişmemeli.

Şirket içi module'lerin varsa GOPRIVATE'i ayarla. Ayarlamazsan Go, private repo'larının adını herkese açık proxy'ye ve checksum database'e sormaya çalışır; bu hem başarısız olur hem de module adlarını dışarı sızdırır. Kurumsal ağlarda Athens ya da Artifactory gibi bir iç proxy kullanıyorsan GOPROXY'yi ona yönlendir, NuGet'te iç feed kullanmak gibi.

CI'daki Go sürümünü bilinçli seç. GOTOOLCHAIN=auto varsayılanı, go.mod daha yeni bir sürüm isterse pipeline'da sessizce toolchain indirir. Bu çoğu zaman işe yarar, ama build'in hangi sürümle yapıldığını loglarda görmek istiyorsan pipeline'da sürümü açıkça kur ve GOTOOLCHAIN=local kullan.

Sık Düşülen Tuzaklar

Her şeyi utils ya da common adlı tek bir package'a koymak. Go'da package adı her çağrıda görünür: utils.FormatPrice okuyana hiçbir şey söylemez, catalog.FormatPrice söyler. Fonksiyonu kullanıldığı domain'in package'ına koy; gerçekten paylaşılan bir şey varsa adı ne yaptığını anlatsın, money ya da isbn gibi.

Import cycle. C#'ta aynı assembly içindeki iki namespace birbirini serbestçe kullanabilir. Go'da package'lar arasında döngü yasak. catalog'un orders'ı, orders'ın da catalog'u import ettiği küçük bir module'de:

go build ./...
package example.com/cyc/catalog
    imports example.com/cyc/orders from catalog.go
    imports example.com/cyc/catalog from orders.go: import cycle not allowed

Çözüm genellikle bağımlılığın yönünü düzeltmek: sipariş kitabı bilir, kitap siparişi bilmez. İki taraf da aynı tipe ihtiyaç duyuyorsa, ya o tipi üçüncü küçük bir package'a taşırsın ya da bir tarafta küçük bir interface tanımlarsın; ikincisini 04'te göreceğiz.

Derin klasör hiyerarşisi kurmak. internal/domain/models/entities/book gibi yollar Go'da import satırlarını uzatır ve package adlarını anlamsızlaştırır. Go'da package'lar düz ve az olur.

go.work'ü commit etmek. Workspace dosyası senin makinendeki klasör düzenini anlatır. Commit edersen CI'da ya da ekip arkadaşının makinesinde olmayan klasörleri arar.

Küçük Bir Deneme

★☆☆ catalog package'ına Count() int diye export edilen bir method ekle ve main.go'dan çağır. Sonra adını count yap ve derleyicinin ne dediğine bak.

★★☆ Projeye cmd/bookstore-import adında ikinci bir komut ekle; sadece catalog.Store{}.All()'daki kitap sayısını yazdırsın. go build -o bin/ ./... ile ikisini birlikte build et. bin klasöründe kaç dosya oluştu?

★★★ Boş bir klasörde go 1.27.0 satırı olan bir module aç, chi'yi import eden küçük bir main.go yaz, go get github.com/go-chi/chi/v5@v5.5.0 çalıştır ve go.mod'a ikinci bir require bloğunu elle ekle. go mod tidy sonrasında blokları say. Sonra go satırını 1.26.0 yapıp aynısını tekrarla.

Proje iskeleti hazır. Bir sonraki yazıda bu iskeletin içini dolduracağımız dilin kendisine geçiyoruz: değişkenler, zero value, string ve rune farkı, slice ile array, map, pointer ve Go'nun tek döngüsü for. Örnek olarak katalogdaki kitapları fiyata göre süzeceğiz.