Tarkibga o'tish

Go’da struct

struct bir-biriga bog‘liq, turli turdagi qiymatlarni bitta yangi turga birlashtiradi. Masalan, mahsulot nomi string, narxi int64, ombordagi holati esa bool bo‘lishi mumkin. Ularni alohida o‘zgaruvchilarda emas, bitta Product qiymatida saqlash kodni aniq qiladi.

Tur yaratish va qiymat berish

package main

import "fmt"

type User struct {
    Name  string
    Age   int
    Email string
}

func main() {
    user := User{
        Name:  "Ali",
        Age:   25,
        Email: "[email protected]",
    }

    fmt.Println(user.Name, user.Age, user.Email)
}

Natija:

type User struct yangi nomlangan tur yaratadi. Name, Age va Email uning maydonlari. Paket tashqarisidan ishlatilishi kerak bo‘lgan tur va maydon nomlari bosh harf bilan boshlanadi.

Nomlangan maydonli literal tartibga bog‘liq emas va yangi maydon qo‘shilganda xavfsizroq. User{"Ali", 25, "[email protected]"} yozish mumkin, ammo maydon tartibi o‘zgarsa kod buziladi; shu sabab amaliy kodda nomlangan ko‘rinish afzal.

Nol qiymat

structning nol qiymatida har bir maydon o‘z turining nol qiymatini oladi:

package main

import "fmt"

type Product struct {
    Name  string
    Price int64
    Stock int
}

func main() {
    var product Product
    fmt.Printf("%q %d %d\n", product.Name, product.Price, product.Stock)
}

Natija:

"" 0 0

Yaxshi loyihalangan tur imkon qadar nol qiymatda ham foydali bo‘ladi. Agar ayrim maydonlar majburiy yoki ma’lum oraliqda bo‘lishi kerak bo‘lsa, konstruktor vazifasidagi funksiya va validatsiya ishlatiladi.

Ichma-ich struct

package main

import "fmt"

type Address struct {
    City   string
    Street string
}

type Customer struct {
    Name    string
    Address Address
}

func main() {
    customer := Customer{
        Name: "Lola",
        Address: Address{
            City:   "Toshkent",
            Street: "Amir Temur",
        },
    }

    fmt.Println(customer.Name, customer.Address.City)
}

Natija:

Lola Toshkent

Bu kompozitsiya: Customer ichida aniq nomlangan Address maydoni bor. Go’da klassik meros olish yo‘q; murakkab turlar odatda kichik turlarni birlashtirish orqali quriladi.

Embedding

Maydon nomisiz tur yozilsa, u joylashtirilgan maydon (embedded field) bo‘ladi:

package main

import "fmt"

type Audit struct {
    CreatedBy string
}

type Order struct {
    ID int
    Audit
}

func main() {
    order := Order{ID: 42, Audit: Audit{CreatedBy: "admin"}}
    fmt.Println(order.ID, order.CreatedBy)
}

Natija:

42 admin

order.CreatedByorder.Audit.CreatedByning qisqa ko‘rinishi. Embedding meros olish emas: Order va Audit alohida turlar bo‘lib qoladi. Nomlar to‘qnashsa, to‘liq yo‘l bilan murojaat qilish kerak.

Qiymat semantikasi, pointer va taqqoslash

struct boshqa o‘zgaruvchiga berilganda maydonlari nusxalanadi. Nusxa ichidagi slice, map yoki pointer esa o‘sha asosiy ma’lumotga murojaat qilishi mumkin; bu chuqur nusxa emas. Asl structni o‘zgartirish kerak bo‘lsa, pointer ishlatiladi.

Barcha maydonlari taqqoslanadigan struct == bilan taqqoslanadi. Slice, map yoki funksiya maydoni bor struct to‘g‘ridan-to‘g‘ri taqqoslanmaydi.

Bo‘sh struct

struct{} maydonsiz tur. U odatda qiymatning o‘zi kerak bo‘lmagan to‘plamlarda ishlatiladi:

package main

import "fmt"

func main() {
    tags := map[string]struct{}{}
    tags["go"] = struct{}{}
    _, bor := tags["go"]
    fmt.Println(bor)
}

Natija:

true

Struct xotirada maydonlar tekislanishi (alignment) sabab maydonlar o‘lchamlari yig‘indisidan ko‘proq joy egallashi mumkin. unsafe.Sizeof bilan o‘lchash mumkin, ammo maydonlarni faqat taxmin bilan qayta tartiblashdan oldin profiler va real talabga qarang.

Xulosa

  • struct bog‘liq qiymatlarni yangi nomlangan turga birlashtiradi.
  • Nomlangan literal maydon tartibiga bog‘liq emas.
  • Nol qiymat har bir maydonning nol qiymatlaridan tuziladi.
  • Embedding qulay murojaat va metod promotion beradi, ammo meros olish emas.
  • Tayinlash sayoz nusxa yaratadi.

Keyingi darsda nomlangan turga xatti-harakat qo‘shadigan metodlar o‘rganiladi.