Если бы вы дали разработчику 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, чтобы узнать больше о том, как мы демократизируем бесплатное обучение программированию по всему миру.