Golang: Структуры и методы в Go
Go — язык со строгой типизацией и поддержкой объектного стиля, но без привычного class. Вместо этого используется сочетание структур (для хранения состояния) и методов (для поведения).
Это позволяет создавать объекты, инкапсулирующие данные и операции над ними — как в ООП, но проще и прямолинейнее.
Объявление структуры
Структура — это пользовательский тип, состоящий из набора полей:
type User struct {
Name string
Age int
}Структура User описывает сущность с двумя полями: Name (строка) и Age (целое число). Теперь User — это новый тип данных, который можно использовать, как любой другой. Чтобы создать значение структуры, используют литерал структуры.
// var user User;
user := User{
Name: "Alice",
Age: 30,
}К полям структуры можно обращаться напрямую:
fmt.Println(user.Name) // => Alice
user.Age = 31Методы
Go позволяет определять методы — это функции, привязанные к типу (например, к структуре). Они выглядят как обычные функции, но с особым параметром — приёмником (receiver), который указывается в скобках перед именем функции. Обращаться к нему можно так же как и любым другим параметрам:
func (u User) Greet() string {
return "Hi, I'm " + u.Name
}Этот метод можно вызвать на экземпляре структуры:
user := User{Name: "Alice", Age: 30}
fmt.Println(user.Greet()) // => Hi, I'm AliceГде описывать методы?
Методы определяются вне структуры, но обязательно в том же пакете. В теле самой структуры можно определить только поля. Вот правильная структура:
package main
import "fmt"
type User struct {
Name string
Age int
}
func (u User) Greet() string {
return "Hi, I'm " + u.Name
}
func main() {
user := User{Name: "Bob"}
fmt.Println(user.Greet()) // => Hi, I'm Bob
}Порядок не имеет значения — метод может быть описан до или после использования структуры. Главное — чтобы тип, к которому он относится, был определён в том же пакете.
Передача структуры в функцию
Со структурами работают не только методы. Как и любой другой тип, структуру можно передавать в обычные функции. Это позволяет использовать её как единое значение, передавая сразу связанный набор данных.
func PrintAge(u User) {
fmt.Println("Возраст:", u.Age)
}Функция PrintAge() получает структуру User и работает с её полями. При этом структура передаётся по значению, то есть копируется. Если изменить ее внутри функции, то изменится копия — оригинал останется без изменений. Такая же логика действует и для методов.
func ChangeName(u User) {
u.Name = "Неизвестно"
}
func (u User) ResetName() {
u.Name = "Без имени"
}
func main() {
user := User{Name: "Alice", Age: 30}
ChangeName(user)
// не изменилось
fmt.Println(user.Name) // => Alice
user.ResetName()
// не изменилось
fmt.Println(user.Name) // => Alice
}Чтобы изменения применялись к оригинальной структуре, нужно передавать указатель. Это мы научимся делать в следующих уроках.
Задание
Создайте структуру Package, которая описывает посылку и содержит два поля:
ID— строка: идентификатор посылки (например, "PKG-1042")Delivered— логическое значение (bool), указывающее доставлена ли посылка
Реализуйте метод Status(), который возвращает статус в виде строки, например:
- Если
Delivered == true, метод возвращает: "Package PKG-1042 has been delivered" - Если
Delivered == false, метод возвращает: "Package PKG-1042 is still in transit"
p1 := Package{ID: "PKG-1042", Delivered: true}
p1.Status() // "Package PKG-1042 has been delivered"
p2 := Package{ID: "PKG-2048", Delivered: false}
p2.Status() // "Package PKG-2048 is still in transit"Полезное
Golang: Структуры и методы в Go
Go — язык со строгой типизацией и поддержкой объектного стиля, но без привычного class. Вместо этого используется сочетание структур (для хранения состояния) и методов (для поведения).
Это позволяет создавать объекты, инкапсулирующие данные и операции над ними — как в ООП, но проще и прямолинейнее.
Объявление структуры
Структура — это пользовательский тип, состоящий из набора полей:
type User struct {
Name string
Age int
}Структура User описывает сущность с двумя полями: Name (строка) и Age (целое число). Теперь User — это новый тип данных, который можно использовать, как любой другой. Чтобы создать значение структуры, используют литерал структуры.
// var user User;
user := User{
Name: "Alice",
Age: 30,
}К полям структуры можно обращаться напрямую:
fmt.Println(user.Name) // => Alice
user.Age = 31Методы
Go позволяет определять методы — это функции, привязанные к типу (например, к структуре). Они выглядят как обычные функции, но с особым параметром — приёмником (receiver), который указывается в скобках перед именем функции. Обращаться к нему можно так же как и любым другим параметрам:
func (u User) Greet() string {
return "Hi, I'm " + u.Name
}Этот метод можно вызвать на экземпляре структуры:
user := User{Name: "Alice", Age: 30}
fmt.Println(user.Greet()) // => Hi, I'm AliceГде описывать методы?
Методы определяются вне структуры, но обязательно в том же пакете. В теле самой структуры можно определить только поля. Вот правильная структура:
package main
import "fmt"
type User struct {
Name string
Age int
}
func (u User) Greet() string {
return "Hi, I'm " + u.Name
}
func main() {
user := User{Name: "Bob"}
fmt.Println(user.Greet()) // => Hi, I'm Bob
}Порядок не имеет значения — метод может быть описан до или после использования структуры. Главное — чтобы тип, к которому он относится, был определён в том же пакете.
Передача структуры в функцию
Со структурами работают не только методы. Как и любой другой тип, структуру можно передавать в обычные функции. Это позволяет использовать её как единое значение, передавая сразу связанный набор данных.
func PrintAge(u User) {
fmt.Println("Возраст:", u.Age)
}Функция PrintAge() получает структуру User и работает с её полями. При этом структура передаётся по значению, то есть копируется. Если изменить ее внутри функции, то изменится копия — оригинал останется без изменений. Такая же логика действует и для методов.
func ChangeName(u User) {
u.Name = "Неизвестно"
}
func (u User) ResetName() {
u.Name = "Без имени"
}
func main() {
user := User{Name: "Alice", Age: 30}
ChangeName(user)
// не изменилось
fmt.Println(user.Name) // => Alice
user.ResetName()
// не изменилось
fmt.Println(user.Name) // => Alice
}Чтобы изменения применялись к оригинальной структуре, нужно передавать указатель. Это мы научимся делать в следующих уроках.
Задание
Создайте структуру Package, которая описывает посылку и содержит два поля:
ID— строка: идентификатор посылки (например, "PKG-1042")Delivered— логическое значение (bool), указывающее доставлена ли посылка
Реализуйте метод Status(), который возвращает статус в виде строки, например:
- Если
Delivered == true, метод возвращает: "Package PKG-1042 has been delivered" - Если
Delivered == false, метод возвращает: "Package PKG-1042 is still in transit"
p1 := Package{ID: "PKG-1042", Delivered: true}
p1.Status() // "Package PKG-1042 has been delivered"
p2 := Package{ID: "PKG-2048", Delivered: false}
p2.Status() // "Package PKG-2048 is still in transit"Полезное
Ваше упражнение проверяется по этим тестам
package solution
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestPackageStatus(t *testing.T) {
a := assert.New(t)
p1 := Package{ID: "PKG-1042", Delivered: true}
a.Equal("Package PKG-1042 has been delivered", p1.Status())
p2 := Package{ID: "PKG-2048", Delivered: false}
a.Equal("Package PKG-2048 is still in transit", p2.Status())
}Решение учителя откроется через:
20:00
