Изучение структур в Go

Структуры — это способ структурировать и использовать данные. Это позволяет нам группировать данные. В этой статье мы увидим, как их объявить и использовать в Go.

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

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

package main
 
import (
    "fmt"
)
 
type Fruit struct {
    name string
}
 
// to define a struct type use
// type structname struct {
//       field1 type1
//       field2 type2
//       ...
// }
 
func main() {
}

Объявление структурных переменных

Мы увидим, как объявить структурную переменную. Это действительно просто, как показано ниже.

var variablename structname   // declare a struct variable

Что такое структура с нулевым значением?

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

package main
 
import (
    "fmt"
)
 
type Fruit struct {
    name string
}
 
func main() {
    var apple Fruit
    fmt.Println(apple)     // prints {}
}

Создание и инициализация структуры в Golang

Теперь мы создадим структуры и инициализируем их значениями. Есть несколько способов сделать это.

1. Использование синтаксиса структурного литерала

Синтаксис структурного литерала — это просто присвоение значений при объявлении, и это действительно просто.

package main
 
import (
    "fmt"
)
 
type Fruit struct {
    name string
}
 
func main() {
    var apple = Fruit{"Apple"} // struct literal syntax
    fmt.Println(apple)     // prints {Apple}
}

2. Использование ключевого слова new

Мы можем использовать ключевое слово new при объявлении структуры. Затем мы можем присвоить значения, используя точечную запись для его инициализации.

package main
 
import (
    "fmt"
)
 
type Fruit struct {
    name string
}
 
func main() {
    var banana = new(Fruit)
    banana.name = "Banana"
    fmt.Println(banana)     // prints &{Banana}
}

3. Использование оператора адреса указателя

Оператор адреса указателя (&) можно использовать для объявления структуры. Давайте посмотрим, как мы это сделаем.

package main
 
import (
    "fmt"
)
 
type Fruit struct {
    name string
}
 
func main() {
    var mango = &Fruit{"Mango"}
    fmt.Println(mango)     // prints &{Mango}
}

Типы структур в Go

Структура может быть как именованной, так и безымянной или анонимной. Оба имеют свое применение. Мы узнаем, что это такое и как их использовать.

1. Именованная структура

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

type Food struct {} // Food is the name

2. Анонимная структура

Теперь мы увидим анонимные структуры. Они очень пригодятся. Мы увидим, как мы их создаём и используем.

package main
 
import (
    "fmt"
)
 
func main() {
     
    pizza := struct {
        name string
    }{
        name: "Pizza",
    }
     
    fmt.Println(pizza)     // prints {Pizza}
}

Поля объекта структуры

Структуры имеют поля. Он может быть именным или безымянным. Им могут быть присвоены значения, или они могут оставаться пустыми и, таким образом, иметь нулевое значение. Давайте посмотрим, как их инициализировать и использовать.

1. Именованные поля в структуре

Именованные поля — это поля, имя которых было объявлено в объявлении типа структуры. Ниже приведен пример.

type Food struct {
        name string        // this field has name
        quantity int       // ...
} 

2. Анонимные поля в структуре

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

package main
 
import (
    "fmt"
)
 
// none of the fields are named
// these are anonymous fields
 
// Throws error because of ambiguity
// There are two string fields to choose from
// p.string makes no sense to the compiler
 
// type Painting struct {
// string          // painting's name
// string          // artist's name
// }
 
type Painting struct {
    string          // painting name
    Artist          // artist
}
 
type Artist struct {
    string
}
 
func main() {
    var p Painting
    p.string = "Starry Night"
    // p.string = "Van Gogh"      // it will throw an error
                                   // "ambiguous selector p.string"
     
    p.Artist.string = "Van Gogh"
    fmt.Println(p)     // prints {Starry Night {Van Gogh}}
}

3. Функции как поле

Структуры могут иметь функции в качестве своего поля. Ниже приведен код, показывающий использование функции внутри структуры.

import (
    "fmt"
)
 
// declare function type
type FoodNameGetter func(string) string
 
type Food struct {
    name string
    getter FoodNameGetter // declare function
}
 
 
func main() {
    pizza := Food{
        name: "Pizza",
        getter: func(name string) string {        // declare function body
            return "This is " + name + "."
        },
    }
     
    fmt.Println(pizza.getter(pizza.name))    // prints "This is Pizza."
}

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

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

// declaration
type Car struct {
        name string
        cost int
}
 
var c Car = Car{"Mercedes", 3500000}
// accessing
carMake := c.name
carPrice := c.cost

Теперь для вложенной структуры мы можем сделать следующее:

package main
 
import (
    "fmt"
)
 
type User struct {
    name string
}
 
type Service struct {
        name string
    user User
}
 
func main() {
 
    google := Service{
        name: "Google",
        user: User{
            name: "John Doe",
        },
    }
 
    // accessing from nested struct
    fmt.Println(google.user.name) // prints "John Doe"
}

Продвигаемые поля

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

package main
 
import (
    "fmt"
)
 
type Person struct {
    name string
}
 
type StoreKeeper struct {
    Person
}
 
func main() {
    var p = StoreKeeper{}
    p.Person = Person{"Jane Doe"}
     
    // access the field as normal field
    fmt.Println(p.name)                  // prints "Jane Doe"
}

Использование указателей структуры

Мы можем создавать указатели на структуру, используя оператор адреса (&) . Вот пример, показывающий именно это.

package main
 
import (
    "fmt"
)
 
type Student struct {
    name string
}
 
func main() {
    ptrStudent := &Student{name: "John"}
     
    fmt.Println(ptrStudent) // prints &{John}
}

Мы можем использовать функцию new() , чтобы получить указатель на эту структуру.

Сравнение структур

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

package main
 
import (
    "fmt"
)
 
type Student struct {
    name string
}
 
func main() {
    s1 := Student{"John"}
    s2 := Student{"John"}
     
    if(s1 == s2) {
        fmt.Println("They are equal")
    } else {
        fmt.Println("They are not equal")
    }
     
    // output: "They are equal"
}

Массив структур

Теперь мы увидим, как использовать структуры в массивах. Это довольно просто и понятно.

1. Объявление и инициализация массива структур

Мы просто объявляем массив с типом этой структуры.

var arrayOfStruct []StructName    // declaration

2. Вставка значений в массив структур

Используйте функцию добавления, которая возвращает фрагмент после вставки.

package main
 
import (
    "fmt"
)
 
type Student struct {
    name string
}
 
func main() {
    // declare array
    var students []Student
     
    s := Student{"Kate"}
    kate := append(students, s)
    fmt.Println(kate)            // [{Kate}]
}

Или мы можем просто использовать такую ​​индексацию.

students[1] = Student{"Peter"}

Вот как мы можем использовать структуры в Go для различных целей.