0 added
0 removed
Original
2026-01-01
Modified
2026-03-10
1
<ul><li><a>Golang interface</a><ul><li><a>Пример использования</a></li>
1
<ul><li><a>Golang interface</a><ul><li><a>Пример использования</a></li>
2
</ul></li>
2
</ul></li>
3
<li><a>Чем полезны интерфейсы?</a></li>
3
<li><a>Чем полезны интерфейсы?</a></li>
4
<li><a>Несколько слов о функции append</a></li>
4
<li><a>Несколько слов о функции append</a></li>
5
</ul><p>Карандаш или шариковая ручка - это конкретные объекты, но как тогда назвать пишущий инструмент? Сам по себе он представляет собой абстрактное понятие, которое нельзя точно описать. Но иногда главная идея заключается в том,<strong>что можно сделать</strong>, а не в том,<strong>чем конкретно это делается</strong>. Поставленную задачу реализуют интерфейсы (interfaces).</p>
5
</ul><p>Карандаш или шариковая ручка - это конкретные объекты, но как тогда назвать пишущий инструмент? Сам по себе он представляет собой абстрактное понятие, которое нельзя точно описать. Но иногда главная идея заключается в том,<strong>что можно сделать</strong>, а не в том,<strong>чем конкретно это делается</strong>. Поставленную задачу реализуют интерфейсы (interfaces).</p>
6
<h2>Golang interface</h2>
6
<h2>Golang interface</h2>
7
<p>В языке программирования Golang существует тип "интерфейс". Для наилучшего понимания этого типа скажем, что большая часть разных типов данных фокусируется на хранимых ими значениях:</p>
7
<p>В языке программирования Golang существует тип "интерфейс". Для наилучшего понимания этого типа скажем, что большая часть разных типов данных фокусируется на хранимых ими значениях:</p>
8
<p>- тип<em>string</em>предназначен для хранения строк;</p>
8
<p>- тип<em>string</em>предназначен для хранения строк;</p>
9
<p>- тип<em>int</em><em>,</em><em>integer</em>- для целых чисел и т. д.</p>
9
<p>- тип<em>int</em><em>,</em><em>integer</em>- для целых чисел и т. д.</p>
10
<p>Однако тип<em>interface</em>отличается. Использование интерфейсов сфокусировано не на сохраняемом значении (value), а на том, что именно этот type делает (вспоминаем пример с пишущим инструментом). А так как методы выражают поведение предоставленного типа, интерфейсы объявляются с набором таких методов, которых этот тип должен удовлетворить.</p>
10
<p>Однако тип<em>interface</em>отличается. Использование интерфейсов сфокусировано не на сохраняемом значении (value), а на том, что именно этот type делает (вспоминаем пример с пишущим инструментом). А так как методы выражают поведение предоставленного типа, интерфейсы объявляются с набором таких методов, которых этот тип должен удовлетворить.</p>
11
<p>Можно вспомнить interface для записи<em>Writer</em>, который существует в стандартной библиотеке Go. Он позволяет записывать:</p>
11
<p>Можно вспомнить interface для записи<em>Writer</em>, который существует в стандартной библиотеке Go. Он позволяет записывать:</p>
12
<p>- текст;</p>
12
<p>- текст;</p>
13
<p>- сжатые архивы;</p>
13
<p>- сжатые архивы;</p>
14
<p>- картинки CSV (CSV -<em>comma-separated values</em>- это значения, разделенные запятыми. Формат CSV популярен у работающих с табличными приложениями - Google Sheets, Microsoft Excel).</p>
14
<p>- картинки CSV (CSV -<em>comma-separated values</em>- это значения, разделенные запятыми. Формат CSV популярен у работающих с табличными приложениями - Google Sheets, Microsoft Excel).</p>
15
<p>Также Writer может записывать вывод на экране, файл на диск, ответ на web-запрос и т. п. То есть Writer представлен одним единым интерфейсом, посредством которого можно записать, что угодно. Вывод прост -<strong>interface очень гибок</strong>, и тот же Writer - простой тому пример.</p>
15
<p>Также Writer может записывать вывод на экране, файл на диск, ответ на web-запрос и т. п. То есть Writer представлен одним единым интерфейсом, посредством которого можно записать, что угодно. Вывод прост -<strong>interface очень гибок</strong>, и тот же Writer - простой тому пример.</p>
16
<p>Ниже объявим переменную типа<em>interface</em>:</p>
16
<p>Ниже объявим переменную типа<em>interface</em>:</p>
17
<p>Созданная нами переменная t способна хранить значение любого типа, а это удовлетворяет интерфейсу. Говоря точнее, данный тип подойдет интерфейсу, если он объявляет метод talk, который не принимает аргументы, возвращая строку.</p>
17
<p>Созданная нами переменная t способна хранить значение любого типа, а это удовлетворяет интерфейсу. Говоря точнее, данный тип подойдет интерфейсу, если он объявляет метод talk, который не принимает аргументы, возвращая строку.</p>
18
<p>Ниже объявляются уже два типа, которые отвечают требованиям:</p>
18
<p>Ниже объявляются уже два типа, которые отвечают требованиям:</p>
19
<p>Пусть martian - это структура (struct) без полей, laser - целое число. Оба типа предоставляют метод talk, а значит, их можно присвоить к t, что и показано ниже:</p>
19
<p>Пусть martian - это структура (struct) без полей, laser - целое число. Оба типа предоставляют метод talk, а значит, их можно присвоить к t, что и показано ниже:</p>
20
<p>Меняемая переменная t может принимать форму martian либо laser. Разработчики утверждают, что интерфейсы обладают полиморфизмом, т. е. присутствует возможность менять форму.</p>
20
<p>Меняемая переменная t может принимать форму martian либо laser. Разработчики утверждают, что интерфейсы обладают полиморфизмом, т. е. присутствует возможность менять форму.</p>
21
<p>В большинстве случаев интерфейсы объявляются в качестве именованных типов, а это уже можно использовать повторно. Есть правило относительно именования типов интерфейса, которое связано с суффиком "<em>-er"</em>. К примеру, тот, кто говорит - это<em>talker (talk+er</em>). </p>
21
<p>В большинстве случаев интерфейсы объявляются в качестве именованных типов, а это уже можно использовать повторно. Есть правило относительно именования типов интерфейса, которое связано с суффиком "<em>-er"</em>. К примеру, тот, кто говорит - это<em>talker (talk+er</em>). </p>
22
<p>Тип интерфейса мы можем применять везде, где используются иные типы. Функция shout ниже имеет параметр talker.</p>
22
<p>Тип интерфейса мы можем применять везде, где используются иные типы. Функция shout ниже имеет параметр talker.</p>
23
<p>Интерфейсы характеризуются гибкостью и показывают ее, когда надо изменить либо расширить код. Если объявить новый тип с методом talk, функция shout станет с ним работать. То есть любой код, который зависит лишь от интерфейса, может оставаться прежним даже в том случае, если имплементации добавляются либо меняются.</p>
23
<p>Интерфейсы характеризуются гибкостью и показывают ее, когда надо изменить либо расширить код. Если объявить новый тип с методом talk, функция shout станет с ним работать. То есть любой код, который зависит лишь от интерфейса, может оставаться прежним даже в том случае, если имплементации добавляются либо меняются.</p>
24
<p>Также interface можно использовать со встраиванием структуры - это особенность языка Go. В коде ниже laser встраивается в starship:</p>
24
<p>Также interface можно использовать со встраиванием структуры - это особенность языка Go. В коде ниже laser встраивается в starship:</p>
25
<h3><strong>Пример использования</strong></h3>
25
<h3><strong>Пример использования</strong></h3>
26
<p>Любой код имплементирует интерфейс, причем даже тот, который уже существует. В программе (program) ниже находится пример реализации вывода выдуманной даты, состоящей из часа дня и дня года.</p>
26
<p>Любой код имплементирует интерфейс, причем даже тот, который уже существует. В программе (program) ниже находится пример реализации вывода выдуманной даты, состоящей из часа дня и дня года.</p>
27
<p>package main import (</p>
27
<p>package main import (</p>
28
<p> "fmt"</p>
28
<p> "fmt"</p>
29
<p> "time"</p>
29
<p> "time"</p>
30
<p>)</p>
30
<p>)</p>
31
<p>// stardate возвращает выдуманное нами измерение времени для указанной даты</p>
31
<p>// stardate возвращает выдуманное нами измерение времени для указанной даты</p>
32
<p>func stardate(t time.Time) float64 {</p>
32
<p>func stardate(t time.Time) float64 {</p>
33
<p> doy := float64(t.YearDay())</p>
33
<p> doy := float64(t.YearDay())</p>
34
<p> h := float64(t.Hour()) / 24.0</p>
34
<p> h := float64(t.Hour()) / 24.0</p>
35
<p> return 1000 + doy + h</p>
35
<p> return 1000 + doy + h</p>
36
<p>}</p>
36
<p>}</p>
37
<p>func main() {</p>
37
<p>func main() {</p>
38
<p> day := time.Date(2012, 8, 6, 5, 17, 0, 0, time.UTC)</p>
38
<p> day := time.Date(2012, 8, 6, 5, 17, 0, 0, time.UTC)</p>
39
<p> fmt.Printf("%.1f Curiosity has landed\n", stardate(day)) // Выводится: 1219.2 Curiosity has landed</p>
39
<p> fmt.Printf("%.1f Curiosity has landed\n", stardate(day)) // Выводится: 1219.2 Curiosity has landed</p>
40
<p>}</p>
40
<p>}</p>
41
<h2>Чем полезны интерфейсы?</h2>
41
<h2>Чем полезны интерфейсы?</h2>
42
<p>Существует ряд причин для применения интерфейсов в Go. Вот некоторые наиболее важные:</p>
42
<p>Существует ряд причин для применения интерфейсов в Go. Вот некоторые наиболее важные:</p>
43
<p>- уменьшается дублирование кода (сокращается объем шаблонного кода);</p>
43
<p>- уменьшается дублирование кода (сокращается объем шаблонного кода);</p>
44
<p>- облегчается применение заглушек в модульных тестах вместо реальных объектов;</p>
44
<p>- облегчается применение заглушек в модульных тестах вместо реальных объектов;</p>
45
<p>- так как интерфейсы - это архитектурный инструмент, они помогают "отвязывать" части вашей кодовой базы.</p>
45
<p>- так как интерфейсы - это архитектурный инструмент, они помогают "отвязывать" части вашей кодовой базы.</p>
46
<h2>Несколько слов о функции append</h2>
46
<h2>Несколько слов о функции append</h2>
47
<p>Представьте, что у вас есть гараж с коллекционными автомобилями. Вы купили новый автомобиль, но он уже не помещается в гараж. Что делать? Придется купить новый, повышенной вместимости. Так и в программировании.</p>
47
<p>Представьте, что у вас есть гараж с коллекционными автомобилями. Вы купили новый автомобиль, но он уже не помещается в гараж. Что делать? Придется купить новый, повышенной вместимости. Так и в программировании.</p>
48
<p>У любого гаража, как и у любого массива, есть конкретная вместимость. Извлеченная часть массива (срез массива, он же слайс) может сфокусироваться на части массива и расти, пока не будет достигнут предел вместимости. Когда "гараж" заполнится, его можно будет заменить гаражом побольше, а потом выполнить добавление (appending) среза в новый гараж большей вместимости.</p>
48
<p>У любого гаража, как и у любого массива, есть конкретная вместимость. Извлеченная часть массива (срез массива, он же слайс) может сфокусироваться на части массива и расти, пока не будет достигнут предел вместимости. Когда "гараж" заполнится, его можно будет заменить гаражом побольше, а потом выполнить добавление (appending) среза в новый гараж большей вместимости.</p>
49
<p>Представим, что у нас есть 5 автомобилей. Встроенная в Golang функция append добавляет (appends) новый элемент к срезу:</p>
49
<p>Представим, что у нас есть 5 автомобилей. Встроенная в Golang функция append добавляет (appends) новый элемент к срезу:</p>
50
dwarfs := []string{"BMW", "Audi", "Ford", "Volkswagen", "Cadillac"} dwarfs = append(dwarfs, "Chrysler")fmt.Println(dwarfs) // Вывод будет: [BMW Audi Ford Volkswagen Cadillac Chrysler]<p>Однако функция append вариативна. Это значит, что есть возможность передать для добавления сразу несколько элементов:</p>
50
dwarfs := []string{"BMW", "Audi", "Ford", "Volkswagen", "Cadillac"} dwarfs = append(dwarfs, "Chrysler")fmt.Println(dwarfs) // Вывод будет: [BMW Audi Ford Volkswagen Cadillac Chrysler]<p>Однако функция append вариативна. Это значит, что есть возможность передать для добавления сразу несколько элементов:</p>
51
dwarfs = append(dwarfs, "Buick", "Pontiac", "Lincoln") fmt.Println(dwarfs) // Вывод будет: [BMW Audi Ford Volkswagen Cadillac Chrysler Buick Pontiac Lincoln] <p>Таким образом в массив было добавлено (appended) несколько элементов.</p>
51
dwarfs = append(dwarfs, "Buick", "Pontiac", "Lincoln") fmt.Println(dwarfs) // Вывод будет: [BMW Audi Ford Volkswagen Cadillac Chrysler Buick Pontiac Lincoln] <p>Таким образом в массив было добавлено (appended) несколько элементов.</p>
52
<p><em>Источники</em>:</p>
52
<p><em>Источники</em>:</p>
53
<ul><li>https://golangs.org/interface;</li>
53
<ul><li>https://golangs.org/interface;</li>
54
<li>https://golangs.org/array-append-make.</li>
54
<li>https://golangs.org/array-append-make.</li>
55
</ul><p>Хотите знать о Go больше? Добро пожаловать на курс в OTUS!</p>
55
</ul><p>Хотите знать о Go больше? Добро пожаловать на курс в OTUS!</p>
56
56