Методы указателей

Последнее обновление: 26.12.2017

При вызове метода, объект структуры, для которого определен метод, передается в него по значению. Что это значит? Рассмотрим следующий пример:

package main
import "fmt"

type person struct{
	name string
	age int
}
func (p person) updateAge(newAge int){
	p.age = newAge
}

func main() {
	
	var tom = person { name: "Tom", age: 24 }
	fmt.Println("before", tom.age)
	tom.updateAge(33)
	fmt.Println("after", tom.age)
}

Для структуры person определен метод updateAge, который принимает параметр newAge и изменяет значение поля age у структуры. То есть при вызове этого метода мы ожидаем, что возраст человека изменится. Однако консольный вывод нам показывает, что значение поля age не изменяется:

before 24
after 24

Потому что при вызове tom.updateAge(33) метод updateAge получает копию структуры tom. То есть структура tom копируется в другой участок памяти, и далее метод updateAge работает с копией, никак не затрагивая оригинальную структуру tom.

Однако такое поведение может быть нежелальтельным. Что если мы всетаки хотим таким образом изменять состояние структуры? В этом случае необходимо использовать указатели на структуры:

package main
import "fmt"

type person struct{
	name string
	age int
}
func (p *person) updateAge(newAge int){
	(*p).age = newAge
}

func main() {
	
	var tom = person { name: "Tom", age: 24 }
	var tomPointer *person = &tom
	fmt.Println("before", tom.age)
	tomPointer.updateAge(33)
	fmt.Println("after", tom.age)
}

Теперь метод updateAge принимает указатель на структуру person: p *person, то есть фактически адрес структуры в памяти. С помощью операции разыменования получаем значение по этому адресу в памяти и меняем поле age:

(*p).age = newAge

В функции main определяем указатель на структуру person и передаем ему адрес структуры tom:

var tomPointer *person = &tom

Затем вызываем метод updateAge:

tomPointer.updateAge(33)

Таким образом, метод updateAge получит адрес, который хранится в tomPointer и по этому адресу обратиться к структуре tom, изменив значение ее свойства age.

before 24
after 33

Стоит отметить, что несмотря на то, что метод updateAge определен для указателя на структуру person, мы по прежнему можем вызывать этот метод и для объекта person:

var tom = person { name: "Tom", age: 24 }
fmt.Println("before", tom.age)		// before 24
tom.updateAge(33)
fmt.Println("after", tom.age)		// after 33
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850