#16 golang Методы - функции для структур и других получателей
Primary tabs
Forums:
Метод — это функция, которая может быть привязана к определённому типу данных. Такой тип данных называется получателем ()
В основе этих типов могут лежать как структуры, так и int, string и любые другие доступные типы в Go.
Привязывание методов к структурам
Для начала рассмотрим методы, которые привязываются к структурам.
Определим именованный тип Person и пару методов к нему, а также проверим как они работают:
type Person struct {
Id int
Name string
}
// Получатель - сама структура
// Не изменяет копию структуры
func (receiver Person) updateName(name string) {
receiver.Name = name
}
// Получатель - указатель на структуру.
// Изменяет оригинальную структуру
func (receiver *Person) setName(name string) {
receiver.Name = name
}
func main() {
Vasya := Person{
Id: 1,
Name: "Вася",
}
Vasya.updateName("Василий")
fmt.Println(Vasya) // {1 Вася}
Vasya.setName("Василий")
fmt.Println(Vasya) // {1 Василий}
}
-- из примера видно, что для того, чтобы реально менять поля структуры с помощью методов нам необходимо указывать получателем указатель на структуру, если же мы указываем просто саму структуру, то функция работает с её копией.
Автоматическое "понимание" типа получателя - "по ссылке" или по значению
Еще в примере выше интересно то, что для setName() мы берем не указатель на структуру, а саму переменную структуры - Go разруливает это ситуацию автоматически, так если мы возьмем указатели в обоих случаях из примера выше и вызовем на них методы, то поведение не изменится:
type Person struct {
Id int
Name string
}
// Получатель - сама структура
// Не изменяет оригинальную структуру
func (receiver Person) updateName(name string) {
receiver.Name = name
}
// Получатель - указатель на структуру.
// Изменяет оригинальную структуру
func (receiver *Person) setName(name string) {
receiver.Name = name
}
func main() {
Vasya := Person{
Id: 1,
Name: "Вася",
}
// попобруем теперь с указателями
(&Vasya).updateName("Василий")
fmt.Println(Vasya) // {1 Вася}
(&Vasya).setName("Василий")
fmt.Println(Vasya) // {1 Василий}
}
"Наследование" методов в структурах
Подобно получению доступа к вложенным полям в структурах при их композиции, можно получать/передавать методы.
Рассмотрим пример сразу со встроенной структурой (в отличии от именованной композии тут всё более запутанно):
type Person struct {
Id int
Name string
IsActive bool
}
func (receiver *Person) setName(name string) {
receiver.Name = name
}
func (receiver *Person) setOwnName(name string) {
receiver.Name = name
}
type Address struct {
Address string
Name string // еще одно поле с именем Name
Person // встроенная структура
}
func (receiver *Address) setName(name string) {
receiver.Name = name
}
func main() {
myAddress := Address{
Address: "Лизюкова",
Name: "Мой адрес",
Person: Person{
Id: 1,
Name: "Петя",
IsActive: true,
},
}
fmt.Println(myAddress)
// {Лизюкова Мой адрес {1 Петя true}}
myAddress.setName("Как бы мой адрес")
fmt.Println(myAddress)
// {Лизюкова Как бы мой адрес {1 Петя true}}
// неперекрытый вложенный метод доступен на первом уровне:
myAddress.setOwnName("Вася")
fmt.Println(myAddress)
// {Лизюкова Как бы мой адрес {1 Петя true}}
// обращение к перерытому имени через полный селектор
myAddress.Person.setName("Саша")
fmt.Println(myAddress)
// {Лизюкова Как бы мой адрес {1 Саша true}}
}
-- подобно ситуации с полями, при перекрытии имен выбирается первым делом метод на верхнем уровне (см. выше какой именно из двух методов setName() отработал)
Также в примере выше следует обратить внимание на строку:
myAddress.Person.setOwnName("Саша")-- не смотря на то, структура встроена, у нас есть возможность вызвать перекрытый методы через "полный селектор"
Методы для других типов данных
Методы могут быть не только у структур, например для слайса:
type MySlice []int
func (sl *MySlice) add(val int) {
*sl = append(*sl, val) // разыменовываем указатель
}
func (sl *MySlice) count() int {
return len(*sl)
}
func main() {
list := MySlice([]int{1, 2})
fmt.Println(list) // [1 2]
list.add(5)
fmt.Println(list, list.count()) //[1 2 5] 3
}
-- тут мы добавили методы добавляения элементов в и подсчета длины, используя в т.ч.разыменование указателей.
Видео-материалы
- : ВкВидео | Ютуб | Телеграм
- Log in to post comments
- 64 reads