Структуры и интерфейсы

В этой главе мы рассмотрим основы структур и интефейсов

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

Интерфесы в Go имеют "утиную" типизацию. Если структура имеет все методы которые указаны в интерфейсе, то структура реализует этот интерфейс. Нет необходимости, как в PHP, при объявлении структуры указывать какие интерфейсы реализует структура.

If it looks like a duck, swims like a duck and quacks like a duck, then it probably is a duck.

Структуры и интерфейсы объявляются при помощи ключевого слова type. Пример:

type LoginMaker interface {
  Login() bool
}

type User struct {
  Name string
  isLogged bool
}

func (u *User) Login() bool {
  u.isLogged = true
  return true
}

user := User{}
user.Name = "Alice"

Если в PHP для отделения имени класса или функции от namespace используется обратный слэш, а для отделения имени метода от имени класса ->, то в Go везде используется точка.


Аналог на PHP

interface LoginMaker
{
  public function Login();
}

class User implements LoginMaker {
  public $name = ''
  private $isLogged = false

  public function Login() {
    $this->isLogged = true
    return true
  }
}

$user = new User()
$user->name = "Alice"

Аналоги публичных методов и свойств начинаются с большой буквы (Name), приватных - с маленькой (isLogged).


При объявлении функции Login на Go мы указали тип, к которому относится данная функция. (u *User). Эта переменная называется ресивер и в какой-то степени является аналогом $this в PHP.

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

Не называйте ресивер this - это ненужная калька с других языков. Обычно названием ресивера служит сокращение имени структуры.

В Go вообще часто применяются сокращения, особенно при названиях пакетов или переменных. В разделе имена переменных рекомендаций по CodeReview для Go сказано:

Короткие имена переменных в Go лучше чем длинные. Это особенно касается локальных переменных с ограниченной областью видимости. Лучше c чем lineCount. Лучше i чем sliceIndex.

Базовое правило: чем дальше от объявления переменная используется, тем более наглядным должно быть имя. Для ресивера метода достаточно одной или двух букв. Такие переменные как индексы циклов или ридеры могут обозначаться одной буквой (i, r). Более необычные вещи и глобальные переменные нуждаются в более наглядных именах.

Значения необходимых свойств можно задать сразу в момент инициализации.

user := User{Name:"Alice"}

results matching ""

    No results matching ""