Структуры в Golang

GolangGolangBeginner
Практиковаться сейчас

💡 Этот учебник переведен с английского с помощью ИИ. Чтобы просмотреть оригинал, вы можете перейти на английский оригинал

Введение

Структура (struct) представляет собой составной тип, который можно использовать для хранения различных типов данных. Она может быть использована для реализации более сложных структур данных. Например, товары в магазине бытовых нужд имеют такие атрибуты, как название товара, категория и цена. Мы можем использовать структуру для их представления.

В этом практическом занятии (LabEx) мы научимся определять и использовать структуры.

Точки знания:

  • Определение структуры
  • Методы экземпляра структуры

Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL go(("Golang")) -.-> go/DataTypesandStructuresGroup(["Data Types and Structures"]) go(("Golang")) -.-> go/ObjectOrientedProgrammingGroup(["Object-Oriented Programming"]) go(("Golang")) -.-> go/BasicsGroup(["Basics"]) go/BasicsGroup -.-> go/values("Values") go/BasicsGroup -.-> go/variables("Variables") go/DataTypesandStructuresGroup -.-> go/structs("Structs") go/DataTypesandStructuresGroup -.-> go/pointers("Pointers") go/ObjectOrientedProgrammingGroup -.-> go/methods("Methods") subgraph Lab Skills go/values -.-> lab-149097{{"Структуры в Golang"}} go/variables -.-> lab-149097{{"Структуры в Golang"}} go/structs -.-> lab-149097{{"Структуры в Golang"}} go/pointers -.-> lab-149097{{"Структуры в Golang"}} go/methods -.-> lab-149097{{"Структуры в Golang"}} end

Определение структуры

Мы можем использовать ключевые слова type и struct для определения структуры. Синтаксис выглядит следующим образом:

type StructName struct {
    FieldName Type
    //...
}

Где:

  • Type представляет собой конкретный тип имени поля, который может быть целым числом, строкой и т.д.
  • StructName должен быть уникальным в рамках одного пакета.
  • Имена полей должны быть уникальными в рамках одной структуры.

Давайте попробуем это. Определим магазин бытовых нужд:

type Store struct {
    ProductType string // product type
    ProductName string // product name
    Price       int    // product price
}

В приведенном выше коде мы определяем структуру с именем Store для магазина бытовых нужд, которая включает тип, название и цену товара.

Поскольку поля типа товара и названия товара имеют один и тот же тип, мы можем упростить код следующим образом:

type Store struct {
    ProductName, ProductType string
    Price                   int
}

Создание экземпляра с использованием var

В предыдущем разделе мы определили структуру Store для магазина бытовых нужд, которая описывает пространство в памяти. Память будет выделена и можно будет использовать поля структуры только после создания экземпляра.

Мы можем использовать ключевое слово var для создания экземпляра структуры:

var InstanceName Structure

Давайте посмотрим на пример создания экземпляра. Создайте файл с именем struct.go и напишите следующий код:

cd ~/project
touch struct.go
package main

import "fmt"

type Store struct {
    productName string
    productType string
    price       int
}

func main() {
    // Instantiate a structure using `var`
    var store1 Store
    // Assign values to the fields related to the instance store1
    store1.productType = "Drinks"
    store1.productName = "Coca-Cola"
    store1.price = 3

    fmt.Printf("store1:\n\t%s\n\t%s\n\t%d\n",
        store1.productType, store1.productName, store1.price)
}

Запустите программу:

go run struct.go

После запуска отобразится следующий результат:

store1:
Drinks
Coca-Cola
3

В этой программе мы создали экземпляр магазина бытовых нужд с использованием var, а затем присвоили значения его полям с помощью оператора ..

Начальное значение структуры

Какое значение будет у экземпляра структуры, если мы только инициализируем его, но не присваиваем значения? Давайте посмотрим на следующий код:

package main

import "fmt"

type Store struct {
    ProductName string
    ProductType string
    Price       int
}

func main() {
    // Instantiate a structure using `var`
    var lan1 Store
    // Print the structure value using %#v
    fmt.Printf("lan1: %#v\n", lan1)
}

Запустите программу:

go run struct.go

Результат выглядит следующим образом:

lan1: main.Store{ProductName:"", ProductType:"", Price:0}

Мы видим, что когда начальное значение не указано, значение экземпляра структуры равно нулевому значению соответствующего типа. Например, строка пустая, а целое число равно 0.

Создание экземпляра с использованием new

В дополнение к использованию ключевого слова var для создания экземпляра, мы также можем использовать ключевое слово new:

package main

import "fmt"

type Store struct {
    productName string
    productType string
    price       int
}

func main() {
    store := new(Store)
    // Use %T to output the type
    fmt.Printf("Type of store: %T\n", store)

    store.productType = "Daily Necessities"
    store.productName = "Umbrella"
    store.price = 20

    fmt.Printf("store:\n\t%s\n\t%s\n\t%d\n",
        store.productType, store.productName, store.price)
}

Запустите программу:

go run struct.go

Результат выглядит следующим образом:

Type of store: *main.Store
store:
        Daily Necessities
        Umbrella
        20

При использовании ключевого слова new для создания экземпляра, "экземпляр", который оно создает, на самом деле является указателем на экземпляр. Операция присвоения значения указателю на структуру аналогична присвоению значения обычной структуре.

Создание экземпляра с использованием :=

Аналогично, мы можем использовать := для создания экземпляра структуры:

package main

import "fmt"

type Store struct {
    productName string
    productType string
    price       int
}

func main() {
    lan3 := Store{}
    lan3.productType = "Fresh Food"
    lan3.productName = "Taiwanese Meatballs"
    lan3.price = 20
    fmt.Printf("lan3:\n\t%s\n\t%s\n\t%d\n",
        lan3.productType, lan3.productName, lan3.price)
}

Запустите программу:

go run struct.go

Результат выглядит следующим образом:

lan3:
    Fresh Food
    Taiwanese Meatballs
    20

Мы можем объединить инициализацию и присваивание значений, вот так:

package main

import "fmt"

type Store struct {
    productName string
    productType string
    price       int
}

func main() {
    lan3 := Store{
        productType: "Fresh Food",
        productName: "Taiwanese Meatballs",
        price:       4,
    }
    fmt.Printf("lan3:\n\t%s\n\t%s\n\t%d\n",
        lan3.productType, lan3.productName, lan3.price)
}

Запустите программу:

go run struct.go

Результат выглядит следующим образом:

lan3:
    Fresh Food
    Taiwanese Meatballs
    4

Когда нам нужно присвоить значения всем полям структуры, мы можем записать значения в порядке, в котором они определены в структуре.

Например, мы переписываем экземпляр lan3 следующим образом:

lan3 := Store{
        "Fresh Food",
        "Taiwanese Meatballs",
        4,
    }

Примечание: Этот синтаксис подходит только для случаев, когда значения присваиваются всем полям.

Итоги

В этом практическом занятии (лабораторной работе) мы рассмотрели структуры и подвели итог по следующим аспектам:

  • Структуры представляют собой составные типы данных, которые могут содержать несколько различных типов данных.
  • Значение неинициализированной структуры равно нулевому значению соответствующего типа.
  • Три способа создания экземпляра структуры.