Если бы вы дали разработчику javascript репозиторий Github, написанный на Go, многие вещи поначалу сбили бы его с толку. Тем не менее, основные объекты путаницы для меня, казалось, всегда вращались вокруг указателей, структур и интерфейсов. Таким образом, вот исчерпывающее руководство по всем трем с точки зрения разработчика javascript.

указатели

JavaScript не зависит от реализации, поэтому такие понятия, как адреса памяти, намеренно отсутствуют в самом языке. Адрес памяти, известный как указатель, обозначает место, где переменная хранится в памяти. Очень редко (или совершенно невозможно) получить доступ к адресу памяти переменной. С другой стороны, в Go это так же просто, как использовать оператор &.

func main() {
 p := 21
 fmt.Println(&p) //0xc000118000
}

Но зачем нам адреса памяти?

Для передачи по ссылке. Все массивы и объекты в JS передаются по ссылке. В Go это нужно делать вручную.

Мы знаем звездочку исключительно как оператор умножения. Однако в Go у него есть еще два применения.

  • Тип указателя:
func main() {
 p := 21
 var l *int = &p //The asterisk infront of int means that this variable can only be equal to a memory address of a integer
 fmt.Println(l) //0xc000118000
}

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

  • Разыменование (возврат значения, хранящегося по адресу памяти)
func main() {
 p := 21
 var l *int = &p 
 fmt.Println(*l) //21
}

Структуры

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

type person struct {
  name   string
  age    int
  gender string
}

Указатели и структуры

Чтобы получить доступ к полю структуры, когда у нас есть указатель на структуру, мы можем написать (*struct).field. Однако такая запись громоздка, поэтому Go позволяет нам писать struct.field без явного разыменования.

func main() {
 v := Person{"Gabriel", 18, "Male"}
 p := &v
 p.name = "Gabriel Inniss"
 fmt.Println(v) //{Gabriel Inniss 18 Male} 
}

Методы

func (p *person) setAge(age int) {
  p.age = age
}

func (p *person) setName(name string) {
  p.name = name
}

Доступ к методам в Go можно получить так же, как и в Javascript, однако для создания метода функции требуется специальный аргумент receiver перед именем функции. Получатель — это тип, который будет получать метод.

func main() {
 v := Person{"Gabriel", 18, "Male"}
 v.setName("Gabe")
 v.setAge(100)
 fmt.Println(v) //{Gabe 100 Male} 
}

Интерфейсы

И, наконец, интерфейсы — это ответ Go на полиморфизм. Основополагающий принцип интерфейсов заключается в том, что вы можете определить набор качеств, которыми должны обладать все типы одного и того же «вида». Если они удовлетворяют этим качествам, они считаются «этого рода». Тогда их можно использовать в тех местах, где используется этот «вид». Это будет иметь больше смысла, когда вы это увидите.

type Animal interface {
    MakeNoise() string
}

func (animal Animal) sleep() {
  fmt.Println("ZZZZZzzzzz")
}
  • Этот интерфейс определяет тип животного, любой другой тип, который удовлетворяет качествам создания шума, будет считаться животным и может использовать метод сна.
type Dog struct {
 Noise string
}

func (d Dog) MakeNoise() string {
 return d.Noise
}

func main() {
 Rufus := Dog{"BARK", "Puppy Chow"}
 fmt.Println(sleep(Rufus)) //ZZZZZzzzzz
}

И вуаля! Вы только что изучили эквиваленты классов, наследования, полиморфизма и передачи по ссылке в Go. У вас есть навыки, чтобы считать себя средним в Голанге. Теперь просто (Иди) и практикуйся, и ты скоро станешь мастером.

Спасибо, что дочитали до конца. Пожалуйста, следите за автором и этой публикацией. Посетите Stackademic, чтобы узнать больше о том, как мы демократизируем бесплатное обучение программированию по всему миру.