Mashqlar
Modullar bo’limi ko’proq amaliyot talab qiladi — buyruqlarni terminalda o’zingiz terib, natijani ko’rish kerak. Har bir mashqni avval mustaqil bajaring: papka oching, fayllarni yozing, buyruqlarni ishga tushiring. Faqat tiqilib qolsangiz yechimni oching. Yechimlarda kerakli buyruqlar, fayl tuzilishi va kutilgan natija ko’rsatilgan.
1. Yangi modul yaratish
hisobot nomli papka oching, uni example.com/hisobot moduliga aylantiring, oddiy main.go yozing va ishga tushiring. go.mod fayli qanday ko’rinadi?
Yechimni ko’rish
$ mkdir hisobot && cd hisobot
$ go mod init example.com/hisobot
go: creating new go.mod: module example.com/hisobotpackage main
import "fmt"
func main() {
fmt.Println("hisobot tayyor")
}module example.com/hisobot
go 1.22$ go run .
hisobot tayyorgo mod init <yo'l> bo’sh papkani modulga aylantiradi; modul yo’li — boshqalar sizni import qiladigan manzil.
2. Nega funksiya ko’rinmayapti?
Sizda narx paketi bor, lekin main.go dan uni chaqirsangiz undefined: narx.hisobla xatosi chiqadi. Sababi nima va uni qanday tuzatasiz? Modul yo’li example.com/dokon.
Yechimni ko’rish
Muammo — funksiya nomi kichik harf bilan boshlanadi, shuning uchun u eksport qilinmagan va faqat o’z paketi ichida ko’rinadi. Nomni katta harfga o’tkazsangiz, boshqa paketdan chaqirsa bo’ladi:
package narx
// Hisobla — eksport qilingan (katta harf bilan).
func Hisobla(soni, birlik int) int {
return soni * birlik
}package main
import (
"fmt"
"example.com/dokon/narx"
)
func main() {
fmt.Println(narx.Hisobla(3, 5000))
}$ go run .
15000Qoida sodda: katta harf — ochiq (eksport), kichik harf — yopiq. Bu struct maydonlariga ham tegishli.
3. Tashqi paket qo’shish va tozalash
Loyihangizga github.com/google/uuid paketini qo’shing, undan UUID generatsiya qilishda foydalaning, so’ng go.mod ni toza holatga keltiring.
Yechimni ko’rish
$ go get github.com/google/uuid
go: added github.com/google/uuid v1.6.0package main
import (
"fmt"
"github.com/google/uuid"
)
func main() {
fmt.Println(uuid.NewString())
}$ go mod tidy
$ go run .
9b2e4f7a-3c1d-4e8b-a6f0-1d2c3b4a5e6fgo get paketni qo’shadi va go.mod ga require github.com/google/uuid v1.6.0 yozadi; go mod tidy esa ortiqchasini olib, yetishmaganini qo’shib, faylni haqiqiy kodga moslaydi. Commit’dan oldin doim go mod tidy qiling.
4. v2 ga o’tish
Modulingiz github.com/foo/hisob moslikni buzuvchi o’zgarish qildi va v2.0.0 ga o’tmoqda. go.mod va import yo’li qanday o’zgaradi?
Yechimni ko’rish
v2 va undan yuqori versiyada major raqam modul yo’lining oxiriga qo’shiladi:
module github.com/foo/hisob/v2
go 1.22Endi boshqalar uni import qilganda ham yo’l oxirida /v2 bo’ladi:
import "github.com/foo/hisob/v2"Versiyani teg bilan chiqarasiz:
$ git tag v2.0.0
$ git push origin v2.0.0Sababi: yo’llari boshqacha bo’lgani uchun bir loyihada v1 va v2 yonma-yon yashay oladi. v0 va v1 yo’lga hech narsa qo’shmaydi — /vN faqat v2 dan boshlanadi.
5. Workspace bilan lokal modullarni bog’lash
mat — kichik kutubxona modul, app — uni ishlatuvchi dastur. mat hali hech qayerga chiqarilmagan. Workspace bilan app ni lokal mat ga bog’lang va ishga tushiring.
Yechimni ko’rish
Tuzilma:
ish/
├── mat/
│ ├── go.mod <- module example.com/mat
│ └── mat.go
└── app/
├── go.mod <- module example.com/app
└── main.gopackage mat
func Qosh(a, b int) int { return a + b }package main
import (
"fmt"
"example.com/mat"
)
func main() {
fmt.Println(mat.Qosh(2, 3))
}ish/ papkasida workspace ochamiz:
$ cd ish
$ go work init ./mat ./appBu go.work faylini yaratadi:
go 1.22
use (
./mat
./app
)$ go run ./app
5Workspace Go ga “bu modulni internetdan emas, lokal papkadan ol” deydi. mat ga kiritgan har o’zgarish app da darrov aks etadi — go get yoki e’lon qilish shart emas. go.work ni git ga qo’shmang.
6. Loyihani cmd/ va internal/ bilan tuzish
dostlar nomli CLI loyihasini standart tuzilishda joylashtiring: kirish nuqtasi cmd/ da, ichki kod internal/ da bo’lsin. Modul yo’li example.com/dostlar.
Yechimni ko’rish
dostlar/
├── go.mod
├── cmd/
│ └── dostlar/
│ └── main.go <- package main, kirish nuqtasi
└── internal/
└── greet/
└── greet.go <- faqat shu loyiha ichida ishlatiladipackage greet
import "fmt"
func Greet(name string) string {
return fmt.Sprintf("Salom, %s!", name)
}package main
import (
"fmt"
"example.com/dostlar/internal/greet"
)
func main() {
fmt.Println(greet.Greet("Ali"))
}$ go run ./cmd/dostlar
Salom, Ali!internal/ ichidagi paketni faqat shu modulning o’zi import qila oladi — tashqi loyihalar yo’q. Shuning uchun greet ni bemalol o’zgartira olasiz. Eslatma: kichik loyihaga bu tuzilma shart emas, faqat o’sib borgan sari qo’llang.
7. Formatlash, tekshiruv va cross-compilation
Loyihani rasmiy uslubga keltiring, shubhali kodni tekshiring, so’ng versiyani binaryga yozib, Windows va Linux (arm64) uchun binary quring.
Yechimni ko’rish
package main
import "fmt"
var version = "dev"
func main() {
fmt.Println("versiya:", version)
}$ go fmt ./...
$ go vet ./...
$ go build -ldflags="-X main.version=1.0.0" -o app .
$ ./app
versiya: 1.0.0-ldflags="-X main.version=1.0.0" linkerga main.version o’zgaruvchisini build paytida to’ldirishni buyuradi. Boshqa platformalar uchun GOOS/GOARCH ni belgilang — qo’shimcha asbob kerak emas:
$ GOOS=windows GOARCH=amd64 go build -o app.exe .
$ GOOS=linux GOARCH=arm64 go build -o app-arm .Mavjud platformalar ro’yxatini go tool dist list da ko’rasiz. Bitta mashinadan barcha platformalarga binary qurish — Go ning eng kuchli tomonlaridan biri.
Bularni yechgan bo’lsangiz, modul yaratishdan boshlab, bog’liqliklarni boshqarish, loyihani tuzish va binary chiqargacha bo’lgan butun oqimni egallagansiz.