Пройти курс: Структуры

В этом учебнике мы узнаем о структурах.

Итак, struct — это определяемый пользователем тип, который содержит набор именованных полей. По сути, он используется для группировки связанных данных в единое целое.

Если вы пришли из объектно-ориентированной среды, считайте, что структуры — это облегченные классы, которые поддерживают композицию, но не наследование.

Определение

Мы можем определить struct следующим образом:

type Person struct {}
Войти в полноэкранный режим Выйти из полноэкранного режима

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

Теперь давайте зададим ей несколько полей:

type Person struct {
    FirstName string
    LastName  string
    Age       int
}
Вход в полноэкранный режим Выход из полноэкранного режима

И если поля имеют одинаковый тип, мы можем их свернуть.

type Person struct {
    FirstName, LastName string
    Age                 int
}
Войти в полноэкранный режим Выйти из полноэкранного режима

Объявление и инициализация

Теперь, когда у нас есть наша структура, мы можем объявить ее так же, как и другие типы данных.

func main() {
    var p1 Person

    fmt.Println("Person 1:", p1)
}
Вход в полноэкранный режим Выход из полноэкранного режима
$ go run main.go
Person 1: {  0}
Вход в полноэкранный режим Выход из полноэкранного режима

Как мы видим, все поля struct инициализируются нулевыми значениями. Так FirstName и LastName установлены в "" пустую строку, а Age установлен в 0.

Мы также можем инициализировать его как «struct literal».

func main() {
    var p1 Person

    fmt.Println("Person 1:", p1)

    var p2 = Person{FirstName: "Karan", LastName: "Pratap Singh", Age: 22}

    fmt.Println("Person 2:", p2)
}
Вход в полноэкранный режим Выход из полноэкранного режима

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

    var p2 = Person{
        FirstName: "Karan",
        LastName:  "Pratap Singh",
        Age:       22,
    }
Войти в полноэкранный режим Выход из полноэкранного режима
$ go run main.go
Person 1: {  0}
Person 2: {Karan Pratap Singh 22}
Войти в полноэкранный режим Выход из полноэкранного режима

Мы также можем инициализировать только подмножество полей.

func main() {
    var p1 Person

    fmt.Println("Person 1:", p1)

    var p2 = Person{
        FirstName: "Karan",
        LastName:  "Pratap Singh",
        Age:       22,
    }

    fmt.Println("Person 2:", p2)

    var p3 = Person{
        FirstName: "Tony",
        LastName:  "Stark",
    }

    fmt.Println("Person 3:", p3)
}
Войти в полноэкранный режим Выход из полноэкранного режима
$ go run main.go
Person 1: {  0}
Person 2: {Karan Pratap Singh 22}
Person 3: {Tony Stark 0}
Войти в полноэкранный режим Выход из полноэкранного режима

Как мы видим, поле возраст человека 3 по умолчанию имеет нулевое значение.

Без имени поля

Go structs также поддерживает инициализацию без имен полей.

func main() {
    var p1 Person

    fmt.Println("Person 1:", p1)

    var p2 = Person{
        FirstName: "Karan",
        LastName:  "Pratap Singh",
        Age:       22,
    }

    fmt.Println("Person 2:", p2)

    var p3 = Person{
        FirstName: "Tony",
        LastName:  "Stark",
    }

    fmt.Println("Person 3:", p3)

    var p4 = Person{"Bruce", "Wayne"}

    fmt.Println("Person 4:", p4)
}
Вход в полноэкранный режим Выход из полноэкранного режима

Но вот в чем загвоздка, нам нужно будет указать все значения во время инициализации, иначе она завершится неудачей.

$ go run main.go
# command-line-arguments
./main.go:30:27: too few values in Person{...}
Вход в полноэкранный режим Выход из полноэкранного режима
    var p4 = Person{"Bruce", "Wayne", 40}

    fmt.Println("Person 4:", p4)
Вход в полноэкранный режим Выход из полноэкранного режима

Мы также можем объявить анонимную структуру.

func main() {
    var p1 Person

    fmt.Println("Person 1:", p1)

    var p2 = Person{
        FirstName: "Karan",
        LastName:  "Pratap Singh",
        Age:       22,
    }

    fmt.Println("Person 2:", p2)

    var p3 = Person{
        FirstName: "Tony",
        LastName:  "Stark",
    }

    fmt.Println("Person 3:", p3)

    var p4 = Person{"Bruce", "Wayne", 40}

    fmt.Println("Person 4:", p4)

    var a = struct {
        Name string
    }{"Golang"}

    fmt.Println("Anonymous:", a)
}
Войти в полноэкранный режим Выход из полноэкранного режима

Доступ к полям

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

func main() {
    var p = Person{
        FirstName: "Karan",
        LastName:  "Pratap Singh",
        Age:       22,
    }

    fmt.Println("FirstName", p.FirstName)
}
Войти в полноэкранный режим Выход из полноэкранного режима

Мы также можем создавать указатели на структуры.

func main() {
    var p = Person{
        FirstName: "Karan",
        LastName:  "Pratap Singh",
        Age:       22,
    }

    ptr := &p

    fmt.Println((*ptr).FirstName)
    fmt.Println(ptr.FirstName)
}
Вход в полноэкранный режим Выход из полноэкранного режима

Оба утверждения равны, так как в Go нам не нужно явно разыменовывать указатель. Мы также можем использовать встроенную функцию new.

func main() {
    p := new(Person)

    p.FirstName = "Karan"
    p.LastName = "Pratap Singh"
    p.Age = 22

    fmt.Println("Person", p)
}
Вход в полноэкранный режим Выход из полноэкранного режима
$ go run main.go
Person &{Karan Pratap Singh 22}
Вход в полноэкранный режим Выход из полноэкранного режима

В качестве примечания: две структуры равны, если все их соответствующие поля также равны.

func main() {
    var p1 = Person{"a", "b", 20}
    var p2 = Person{"a", "b", 20}

    fmt.Println(p1 == p2)
}
Войти в полноэкранный режим Выход из полноэкранного режима
$ go run main.go
true
Войти в полноэкранный режим Выход из полноэкранного режима

Экспортируемые поля

Теперь давайте узнаем, что такое экспортируемые и неэкспортируемые поля в struct. Как и правила для переменных и функций, если поле struct объявлено с идентификатором в нижнем регистре, оно не будет экспортировано и будет видно только тому пакету, в котором оно определено.

type Person struct {
    FirstName, LastName  string
    Age                  int
    zipCode              string
}
Вход в полноэкранный режим Выход из полноэкранного режима

Таким образом, поле zipCode не будет экспортировано. То же самое относится и к структуре Person, если мы переименуем ее в person, она также не будет экспортирована.

type person struct {
    FirstName, LastName  string
    Age                  int
    zipCode              string
}
Вход в полноэкранный режим Выход из полноэкранного режима

Встраивание и композиция

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

type Person struct {
    FirstName, LastName  string
    Age                  int
}

type SuperHero struct {
    Person
    Alias string
}
Вход в полноэкранный режим Выход из полноэкранного режима

Итак, наша новая структура будет иметь все свойства исходной структуры. И она должна вести себя так же, как наша обычная структура.

func main() {
    s := SuperHero{}

    s.FirstName = "Bruce"
    s.LastName = "Wayne"
    s.Age = 40
    s.Alias = "batman"

    fmt.Println(s)
}
Вход в полноэкранный режим Выход из полноэкранного режима
$ go run main.go
{{Bruce Wayne 40} batman}
Войти в полноэкранный режим Выйти из полноэкранного режима

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

type Person struct {
    FirstName, LastName  string
    Age                  int
}

type SuperHero struct {
    Person Person
    Alias  string
}
Войти в полноэкранный режим Выход из полноэкранного режима

Следовательно, мы можем переписать наш пример и с композицией.

func main() {
    p := Person{"Bruce", "Wayne", 40}
    s := SuperHero{p, "batman"}

    fmt.Println(s)
}
Вход в полноэкранный режим Выход из полноэкранного режима
$ go run main.go
{{Bruce Wayne 40} batman}
Войти в полноэкранный режим Выход из полноэкранного режима

Опять же, здесь нет правильного или неправильного, но, тем не менее, встраивание иногда бывает полезным.

Теги структур

Тег struct — это просто тег, который позволяет нам прикрепить к полю информацию метаданных, которая может быть использована для пользовательского поведения с помощью пакета reflect.

Давайте узнаем, как мы можем определять теги struct.

type Animal struct {
    Name    string `key:"value1"`
    Age     int    `key:"value2"`
}
Вход в полноэкранный режим Выход из полноэкранного режима

Теги часто встречаются в пакетах кодирования, таких как XML, JSON, YAML, ORMs и управление конфигурацией.

Вот пример тегов для кодировщика JSON.

type Animal struct {
    Name    string `json:"name"`
    Age     int    `json:"age"`
}
Вход в полноэкранный режим Выход из полноэкранного режима

Свойства

Наконец, давайте обсудим свойства структур.

Структуры — это типы значений. Когда мы присваиваем одну переменную struct другой, создается и присваивается новая копия struct.

Аналогично, когда мы передаем struct другой функции, функция получает свою собственную копию struct.

package main

import "fmt"

type Point struct {
    X, Y float64
}

func main() {
    p1 := Point{1, 2}
    p2 := p1 // Copy of p1 is assigned to p2

    p2.X = 2

    fmt.Println(p1) // Output: {1 2}
    fmt.Println(p2) // Output: {2 2}
}
Вход в полноэкранный режим Выход из полноэкранного режима

Пустая структура занимает ноль байт памяти.

package main

import (
    "fmt"
    "unsafe"
)

func main() {
    var s struct{}
    fmt.Println(unsafe.Sizeof(s)) // Output: 0
}
Войти в полноэкранный режим Выход из полноэкранного режима

Эта статья является частью моего открытого курса по Go, доступного на Github.

karanpratapsingh / go-course

Освойте основы и расширенные возможности языка программирования Go

Курс по Go

Привет, добро пожаловать на курс, и спасибо за изучение Go. Я надеюсь, что этот курс обеспечит вам отличный опыт обучения.

Этот курс также доступен на моем сайте, а также на Educative.io

Оглавление

  • Начало работы

    • Что такое Go?
    • Зачем изучать Go?
    • Установка и настройка
  • Глава I

    • Hello World
    • Переменные и типы данных
    • Форматирование строк
    • Управление потоком данных
    • Функции
    • Модули
    • Рабочие пространства
    • Пакеты
    • Полезные команды
    • Сборка
  • Глава II

    • Указатели
    • Структуры
    • Методы
    • Массивы и фрагменты
    • Карты
  • Глава III

    • Интерфейсы
    • Ошибки
    • Паника и восстановление
    • Тестирование
    • Дженерики
  • Глава IV

    • Параллелизм
    • Гороутины
    • Каналы
    • Выбрать
    • Пакет синхронизации
    • Расширенные шаблоны параллелизма
    • Контекст
  • Приложение

    • Следующие шаги
    • Ссылки

Что такое Go?

Go (также известный как Golang) — это язык программирования, разработанный в Google в 2007 году и открытый в 2009 году.

Основное внимание в нем уделяется простоте, надежности и эффективности. Он был разработан, чтобы объединить эффективность, скорость и безопасность статически типизированного и компилируемого языка с легкостью…

Посмотреть на GitHub

Оцените статью
devanswers.ru
Добавить комментарий