HTML Diff
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