💬Для чего в программах на Go используются функции?
Функции в Go играют ключевую роль, предлагая способ организации кода, повторного использования логики и разделения задач на меньшие, управляемые компоненты. Они выполняют несколько важных задач:
1️⃣Модульность и организация кода: функции позволяют разбивать программу на меньшие блоки, улучшая читаемость и понимание кода. Это способствует созданию более структурированных и поддерживаемых программ.
2️⃣Повторное использование кода: после написания функции ее можно использовать многократно в разных частях программы или даже в разных программах. Это сокращает дублирование кода и упрощает обновления.
3️⃣Абстракция и инкапсуляция: функции позволяют абстрагироваться от деталей реализации, сосредоточив внимание на функциональности. Это улучшает понимание кода и уменьшает сложность. Кроме того, функции могут создавать границы, предотвращая воздействие изменений в одной части программы на другие.
4️⃣Тестирование: разбиение программы на функции упрощает процесс тестирования. Мы можем тестировать каждую функцию независимо, что делает обнаружение и устранение ошибок более эффективными.
5️⃣Разделение задач: функции позволяют разделять сложные задачи на меньшие подзадачи. Это делает разработку более систематической, позволяя решать проблемы последовательно и шаг за шагом.
Функции в Go играют ключевую роль, предлагая способ организации кода, повторного использования логики и разделения задач на меньшие, управляемые компоненты. Они выполняют несколько важных задач:
1️⃣Модульность и организация кода: функции позволяют разбивать программу на меньшие блоки, улучшая читаемость и понимание кода. Это способствует созданию более структурированных и поддерживаемых программ.
2️⃣Повторное использование кода: после написания функции ее можно использовать многократно в разных частях программы или даже в разных программах. Это сокращает дублирование кода и упрощает обновления.
3️⃣Абстракция и инкапсуляция: функции позволяют абстрагироваться от деталей реализации, сосредоточив внимание на функциональности. Это улучшает понимание кода и уменьшает сложность. Кроме того, функции могут создавать границы, предотвращая воздействие изменений в одной части программы на другие.
4️⃣Тестирование: разбиение программы на функции упрощает процесс тестирования. Мы можем тестировать каждую функцию независимо, что делает обнаружение и устранение ошибок более эффективными.
5️⃣Разделение задач: функции позволяют разделять сложные задачи на меньшие подзадачи. Это делает разработку более систематической, позволяя решать проблемы последовательно и шаг за шагом.
👍11🥱7🤔2
💬Как в Go реализована композиция (агрегация)? Чем она отличается от наследования?
📌В Go композиция достигается путем встраивания одной структуры в другую. Например, встраивание одной структуры в другую позволяет получить доступ к полям встроенной структуры, как если бы они были полями внешней структуры. Композиция в Go более гибкая и рекомендуется как альтернатива наследованию.
📌В нашем примере:
• Определен базовый тип Engine с двумя полями (Power и Type) и методом Start.
• Определен тип Car, в который встраивается Engine.
• В функции main создается экземпляр типа Car, и через этот экземпляр вызывается метод Start встроенного типа Engine, а также обращаются к полям встроенного типа Engine.
📌Таким образом, композиция в Go позволяет объединять простые типы в более сложные структуры, сохраняя при этом простоту и ясность кода.
📌В Go композиция достигается путем встраивания одной структуры в другую. Например, встраивание одной структуры в другую позволяет получить доступ к полям встроенной структуры, как если бы они были полями внешней структуры. Композиция в Go более гибкая и рекомендуется как альтернатива наследованию.
📌В нашем примере:
• Определен базовый тип Engine с двумя полями (Power и Type) и методом Start.
• Определен тип Car, в который встраивается Engine.
• В функции main создается экземпляр типа Car, и через этот экземпляр вызывается метод Start встроенного типа Engine, а также обращаются к полям встроенного типа Engine.
📌Таким образом, композиция в Go позволяет объединять простые типы в более сложные структуры, сохраняя при этом простоту и ясность кода.
👍14🔥3🤔3
🧑💻 Статьи для IT: как объяснять и распространять значимые идеи
Напоминаем, что у нас есть бесплатный курс для всех, кто хочет научиться интересно писать — о программировании и в целом.
Что: семь модулей, посвященных написанию, редактированию, иллюстрированию и распространению публикаций.
Для кого: для авторов, копирайтеров и просто программистов, которые хотят научиться интересно рассказывать о своих проектах.
👉Материалы регулярно дополняются, обновляются и корректируются. А еще мы отвечаем на все учебные вопросы в комментариях курса.
Напоминаем, что у нас есть бесплатный курс для всех, кто хочет научиться интересно писать — о программировании и в целом.
Что: семь модулей, посвященных написанию, редактированию, иллюстрированию и распространению публикаций.
Для кого: для авторов, копирайтеров и просто программистов, которые хотят научиться интересно рассказывать о своих проектах.
👉Материалы регулярно дополняются, обновляются и корректируются. А еще мы отвечаем на все учебные вопросы в комментариях курса.
💬Что будет при чтении/записи из закрытого и неинициализированного канала?
📌Чтение из закрытого канала: когда мы пытаемся читать из закрытого канала, происходит следующее:
1. Если в канале остались значения, которые были в него предварительно записаны, операция чтения будет успешной.
2. Если в канале больше нет значений, операция чтения немедленно завершится, и полученное значение будет нулевым значением для типа данных канала.
3. Если канал уже закрыт и в нем нет значений, попытка прочитать из него снова приведет к получению нулевого значения для типа данных канала.
📌Запись в закрытый канал: попытка записать в закрытый канал вызовет панику. Это означает, что запись в закрытый канал является недопустимой операцией.
📌Чтение из неинициализированного (nil) канала будет заблокировано, как и запись в неициализированный (nil) канал.
☝️Важно отслеживать состояния каналов, инициализировать и закрывать их по мере необходимости, чтобы избежать паник и непредсказуемого поведения.
📌Чтение из закрытого канала: когда мы пытаемся читать из закрытого канала, происходит следующее:
1. Если в канале остались значения, которые были в него предварительно записаны, операция чтения будет успешной.
2. Если в канале больше нет значений, операция чтения немедленно завершится, и полученное значение будет нулевым значением для типа данных канала.
3. Если канал уже закрыт и в нем нет значений, попытка прочитать из него снова приведет к получению нулевого значения для типа данных канала.
ch := make(chan int)
close(ch)
value, ok := <-ch
fmt.Println(value, ok)
// 0 false📌Запись в закрытый канал: попытка записать в закрытый канал вызовет панику. Это означает, что запись в закрытый канал является недопустимой операцией.
ch := make(chan int)
close(ch)
ch <- 42
// panic: send on closed channel📌Чтение из неинициализированного (nil) канала будет заблокировано, как и запись в неициализированный (nil) канал.
☝️Важно отслеживать состояния каналов, инициализировать и закрывать их по мере необходимости, чтобы избежать паник и непредсказуемого поведения.
👍8😁2⚡1
💬Что такое паника (panic) в Go? Какие операции автоматически возвращают панику и останавливают программу?
📌Паники относятся к категории ошибок, которые не ожидались разработчиком. Паника похожа на исключения в других ЯП и предназначена только для ошибок времени выполнения, например:
🔸Доступ к индексу за пределами массива/среза: попытка доступа к элементу массива или среза по индексу за пределами его размера приведет к панике.
🔸Type assertion:
неправильное приведение типа с помощью type assertion может вызвать панику.
🔸Закрытие закрытого канала:
попытка закрыть уже закрытый канал вызовет панику.
📌Обработка паники
Для обработки паники в Go используется конструкция
Если функция
👉 Подробнее
📌Паники относятся к категории ошибок, которые не ожидались разработчиком. Паника похожа на исключения в других ЯП и предназначена только для ошибок времени выполнения, например:
🔸Доступ к индексу за пределами массива/среза: попытка доступа к элементу массива или среза по индексу за пределами его размера приведет к панике.
arr := []int{1, 2, 3}
fmt.Println(arr[5])
// panic: runtime error: index out of range🔸Type assertion:
неправильное приведение типа с помощью type assertion может вызвать панику.
var i interface{} = "hello"
fmt.Println(i.(int))
// panic: interface conversion: interface {} is string, not int🔸Закрытие закрытого канала:
попытка закрыть уже закрытый канал вызовет панику.
ch := make(chan int)
close(ch)
close(ch)
// panic: close of closed channel📌Обработка паники
Для обработки паники в Go используется конструкция
recover
. Recover
возвращает значение, переданное функции panic
, если вызов recover
происходит в той же горутине, что и panic
. Это часто используется в сочетании с defer
, чтобы обеспечить обработку паники и предотвратить завершение всей программы.func main() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered from panic:", r)
}
}()
causePanic()
fmt.Println("This line will not be reached")
}
func causePanic() {
panic("This is a panic")
}
Если функция
causePanic
вызывает панику, функция defer
будет вызвана перед завершением программы. Функция recover
затем используется для захвата значения паники и предотвращения завершения программы.👉 Подробнее
Digitalocean
Обработка паник в Go | DigitalOcean
Ошибки, возникающие в программе, относятся к двум широким категориям: ожидаемые программистом ошибки и ошибки, возникновения которых не ожидалось. Интерфейс …
👍10❤2
💬В чем разница между context.Background() и context.TODO()?
📌Разница между
👉
📌Разница между
context.Background()
и context.TODO()
в основном заключается в их семантическом использовании.👉
context.Background()
используется как стартовый контекст, а context.TODO()
указывает на то, что контекст будет предоставлен позже, другими словами, когда неясно, какой контекст использовать, или он еще недоступен. С точки зрения функциональности они идентичны.🔥13👍2
💬Что из себя представляет стабы (stubs) и моки (mock) в контексте тестирования в Go?
📌Стабы (stubs) и моки (mocks) являются техниками, используемыми для изоляции тестируемого кода от внешних зависимостей во время тестирования в Go.
🔸Стабы (stubs) — это фейковые объекты, которые предоставляют предопределенные ответы на вызовы методов во время тестирования.
🔸Моки (mocks) — это более продвинутые фейковые объекты, которые, кроме предоставления предопределенных ответов, также проверяют, как и когда методы были вызваны в тестах, что помогает в проверке взаимодействия между объектами.
📌В первом примере создается стаб
📌Стабы (stubs) и моки (mocks) являются техниками, используемыми для изоляции тестируемого кода от внешних зависимостей во время тестирования в Go.
🔸Стабы (stubs) — это фейковые объекты, которые предоставляют предопределенные ответы на вызовы методов во время тестирования.
package main
import "fmt"
type DatabaseStub struct{}
func (db *DatabaseStub) GetUserName(id int) string {
return "Alice"
}
type Database interface {
GetUserName(id int) string
}
func PrintUserName(db Database, id int) {
name := db.GetUserName(id)
fmt.Println(name)
}
func main() {
dbStub := &DatabaseStub{}
PrintUserName(dbStub, 1)
}
🔸Моки (mocks) — это более продвинутые фейковые объекты, которые, кроме предоставления предопределенных ответов, также проверяют, как и когда методы были вызваны в тестах, что помогает в проверке взаимодействия между объектами.
package main
import (
"github.com/stretchr/testify/mock"
"testing"
)
type DatabaseMock struct {
mock.Mock
}
func (db *DatabaseMock) GetUserName(id int) string {
args := db.Called(id)
return args.String(0)
}
func TestPrintUserName(t *testing.T) {
dbMock := new(DatabaseMock)
dbMock.On("GetUserName", 1).Return("Alice")
name := dbMock.GetUserName(1)
dbMock.AssertExpectations(t)
}
📌В первом примере создается стаб
DatabaseStub
, который имеет метод GetUserName
. Во втором примере создается мок DatabaseMock
с использованием библиотеки testify
, который проверяет, был ли метод GetUserName
вызван с правильным аргументом.👍5⚡1
💬Что из себя представляют структурные теги в Go?
🔸Теги структур в Go — это метаданные, прикрепленные к полям структуры, которые могут быть использованы для предоставления дополнительной информации или инструкций внешним пакетам или библиотекам.
🔸Они представляют собой строковые литералы, расположенные в бэктиках (`` ` ``) в объявлении поля структуры.
📌Пример тега структуры в Go:
🔸В этом примере `
📌Теги структур могут быть использованы для различных целей, включая:
1. Контроль сериализации и десериализации: теги могут указывать, как поля должны быть сериализованы или десериализованы в форматы, такие как JSON или XML. Например, тег `
2. Валидация данных: теги могут быть использованы для указания правил валидации для полей, например, минимальной или максимальной длины строки.
3. Описания и документация: теги могут содержать документацию или описания полей.
4. Оркестровка баз данных: теги могут быть использованы для маппинга полей структуры на столбцы в базе данных.
5. Другие кастомные обработки: теги могут быть использованы для произвольной обработки кастомными библиотеками или кодом.
Для доступа к тегам структуры и их разбора часто используется пакет `
👉 Подробнее
🔸Теги структур в Go — это метаданные, прикрепленные к полям структуры, которые могут быть использованы для предоставления дополнительной информации или инструкций внешним пакетам или библиотекам.
🔸Они представляют собой строковые литералы, расположенные в бэктиках (`` ` ``) в объявлении поля структуры.
📌Пример тега структуры в Go:
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
}
🔸В этом примере `
json:"name"
` и `json:"age"
` являются тегами структуры для полей `Name
` и `Age
` соответственно. Эти теги могут быть использованы пакетом `encoding/json
` для управления тем, как объекты `Person
` сериализуются/десериализуются в/из JSON.📌Теги структур могут быть использованы для различных целей, включая:
1. Контроль сериализации и десериализации: теги могут указывать, как поля должны быть сериализованы или десериализованы в форматы, такие как JSON или XML. Например, тег `
json:"name,omitempty"
` указывает, что поле `Name
` должно быть сериализовано как `name
` в JSON, и если поле пустое, его следует опустить.2. Валидация данных: теги могут быть использованы для указания правил валидации для полей, например, минимальной или максимальной длины строки.
3. Описания и документация: теги могут содержать документацию или описания полей.
4. Оркестровка баз данных: теги могут быть использованы для маппинга полей структуры на столбцы в базе данных.
5. Другие кастомные обработки: теги могут быть использованы для произвольной обработки кастомными библиотеками или кодом.
Для доступа к тегам структуры и их разбора часто используется пакет `
reflect
`. Этот пакет предоставляет функции для работы с типами и значениями во время выполнения, что позволяет изучать и изменять значения, типы и теги структур во время выполнения.Please open Telegram to view this post
VIEW IN TELEGRAM
Digitalocean
Использование тегов структур в Go | DigitalOcean
Структуры используются для сбора различных элементов информации внутри одной единицы. Эти наборы информации используются для описания концепций более высоког…
👍12❤2
💬Что такое `json:,omitempty` в контексте структур Go?
🔹Если вы читали предыдущий пост, наверняка заметили упоминание аннотации `
🔹`
🔹В приведенном выше примере без тега
👉 Подробнее
🔹Если вы читали предыдущий пост, наверняка заметили упоминание аннотации `
json:,omitempty
`. Например:type fruit struct {
Name string
Length int `json:,omitempty`
}
🔹`
json:,omitempty
` — это тег JSON для поля в структуре. Если при демаршаллинге данных JSON в структуру это конкретное поле пусто, оно будет игнорироваться. Без тега omitempty
будет использоваться значение по умолчанию.🔹В приведенном выше примере без тега
omitempty
поле длины будет заполнено значением int 0
. Если тип пустого поля — строка, "" (пустая строка) будет значением по умолчанию. Аналогично, значение по умолчанию для логического типа — false
, nil
для указателя, интерфейса, среза и мапы.Please open Telegram to view this post
VIEW IN TELEGRAM
Codingcucumbers
What Is json:,omitempty In Go?
Find out more about the omitempty tag in Go - how to use them, when to use them and more about tags in general
👍8🤔1
💬Какова цель функции init() в Go?
📌Функция
📌Несколько ключевых моментов:
1. Автоматический вызов: функция
2. Использование: функции
3. Несколько функций
4. В случае зависимостей между пакетами, функции
👉 Подробнее
📌Функция
init()
в Go вызывается автоматически при инициализации пакета. В Go нет конструкторов в классическом понимании, как в некоторых других ЯП, но функция init()
предлагает возможность выполнять необходимую начальную настройку. 📌Несколько ключевых моментов:
1. Автоматический вызов: функция
init()
вызывается автоматически перед вызовом main()
и не требует явного вызова.2. Использование: функции
init()
можно использовать для инициализации глобальных переменных, проверки или установки конфигурации, установки соединений с базами данных и других целей.3. Несколько функций
init()
: в одном пакете можно иметь несколько функций init()
. Они будут вызваны в том порядке, в котором объявлены в файле.4. В случае зависимостей между пакетами, функции
init()
из импортированных пакетов выполняются перед функцией init()
из основного пакета.Please open Telegram to view this post
VIEW IN TELEGRAM
Digitalocean
Функция init в Go | DigitalOcean
В Go заданнная функция init() выделяет элемент кода, который запускатся до любой другой части вашего пакета. Этот код запускается сразу же после импорта паке…
👍5
💬Как переобъявить переменные с помощью коротких объявлений?
📌В одной области видимости нельзя переобъявлять переменные, но это можно делать в объявлении нескольких переменных (multi-variable declarations), среди которых хотя бы одна — новая. Переобъявляемые переменные должны располагаться в том же блоке, иначе получится затенённая переменная.
📌Неправильно:
📌Правильно:
📌В одной области видимости нельзя переобъявлять переменные, но это можно делать в объявлении нескольких переменных (multi-variable declarations), среди которых хотя бы одна — новая. Переобъявляемые переменные должны располагаться в том же блоке, иначе получится затенённая переменная.
📌Неправильно:
func main() {
one := 0
one := 1
// ошибка компиляции
}
📌Правильно:
func main() {
one := 0
one, two := 1,2
one,two = two,one
}
👍10
💬В чем разница между пакетами и модулями Go?
📌В Go, пакет — это коллекция исходных файлов
📌Файлы для одного пакета должны находиться в одной директории. Полное имя для пакета строится из имени модуля и пути к директории с файлами.
◆ Например, в
◆ Например, в дереве исходников нашей библиотеки есть файлы в директоории
📌В Go, пакет — это коллекция исходных файлов
.go
в одной директории и с одинаковой директивой package
, в то время как модуль — это дерево пакетов. Имя модуля задаётся в go.mod
.📌Файлы для одного пакета должны находиться в одной директории. Полное имя для пакета строится из имени модуля и пути к директории с файлами.
◆ Например, в
go.mod
указано module example.org/mylib
, тогда все пакеты из модуля example.org/mylib
должны быть в дочерних директориях относительно go.mod
, и путь к директории определяет имя пакета.◆ Например, в дереве исходников нашей библиотеки есть файлы в директоории
./cmd/root
. Тогда эти файлы должны быть либо с директивой package root
, либо package root_test
. И полное имя пакета для этих файлов будет либо example.org/mylib/cmd/root
, либо example.org/mylib/cmd/root_test
(
тесты для пакета example.org/mylib/cmd/root)
.👍12
💬Предположим, что мы хотим выполнить код Go в какой-то момент в будущем или повторно через определенный интервал. Что необходимо использовать в таком случае?
📌Встроенные функции
🔹Таймеры (первый пример):
◆ Таймеры представляют собой способ ожидания определенного времени перед выполнением действия.
◆ Создание таймера выполняется с помощью функции
◆ В примере таймер имеет канал
◆ Также возможно остановить таймер перед его активацией с помощью метода
🔹Тикеры (второй пример):
◆ Тикеры используются для выполнения действий через регулярные промежутки времени.
◆ Создание тикера также выполняется с помощью функции в пакете
◆ Аналогично таймерам, тикеры имеют канал
◆ Тикеры можно остановить, используя метод
📌Встроенные функции
timer
и ticker
упрощают обе задачи, при этом таймеры предназначены для кейсов, когда мы хотим сделать что-то один раз в будущем, а тикеры — для кейсов, когда мы хотим сделать что-то повторно через определенные промежутки времени.🔹Таймеры (первый пример):
◆ Таймеры представляют собой способ ожидания определенного времени перед выполнением действия.
◆ Создание таймера выполняется с помощью функции
time.NewTimer()
; в нее передаем длительность времени, которую необходимо ожидать.◆ В примере таймер имеет канал
C
, в который будет отправлено значение после истечения заданного времени.◆ Также возможно остановить таймер перед его активацией с помощью метода
Stop()
.🔹Тикеры (второй пример):
◆ Тикеры используются для выполнения действий через регулярные промежутки времени.
◆ Создание тикера также выполняется с помощью функции в пакете
time
, в данном случае time.NewTicker()
, с указанием интервала между «тиками».◆ Аналогично таймерам, тикеры имеют канал
C
, в который отправляется значение на каждом «тике».◆ Тикеры можно остановить, используя метод
Stop()
, что предотвратит дальнейшее отправление значений.👍9🥱4
💬Как обрабатывать сигналы Unix в Go?
🔸Обработка сигналов UNIX в Go обычно выполняется с использованием пакета
📌Простой пример:
1. Импортируем пакет
2. Создаем канал, который будет использоваться для получения сигналов:
3. Используем функцию
4. Используем
// обработка сигнала
📌Программа ожидает сигналы
👉 Подробнее
🔸Обработка сигналов UNIX в Go обычно выполняется с использованием пакета
os/signal
. 📌Простой пример:
1. Импортируем пакет
os/signal
и syscall
:import (
"os"
"os/signal"
"syscall"
)
2. Создаем канал, который будет использоваться для получения сигналов:
signals := make(chan os.Signal, 1)
3. Используем функцию
signal.Notify
, чтобы указать, какие сигналы мы хотим обрабатывать:signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM)
4. Используем
select
в горутине или в основном потоке программы для ожидания сигналов и реагирования на них:select {
case sig := <-signals:
// обработка сигнала
fmt.Printf("received signal %v\n", sig)
}
📌Программа ожидает сигналы
SIGINT
и SIGTERM
, и когда она их получит, выведет полученный сигнал. Это базовый пример того, как можно обрабатывать сигналы в Go. 👉 Подробнее
👍13
💬 Что возвращает функция len() в Go, если ей передана строка в кодировке UTF-8?
🔸Функция
🔸Если строка закодирована в UTF-8, каждый символ может занимать от 1 до 4 байтов.
🔸Таким образом, если в строке UTF-8 присутствуют многобайтовые символы, функция
🔸Результат:
Byte length: 6
Rune count: 2
🔸Функция
len()
в Go возвращает количество байтов в строке, а не количество рун (символов Unicode).🔸Если строка закодирована в UTF-8, каждый символ может занимать от 1 до 4 байтов.
🔸Таким образом, если в строке UTF-8 присутствуют многобайтовые символы, функция
len()
вернет значение, большее, чем количество символов в строке.
import (
"fmt"
"unicode/utf8"
)
func main() {
s := "世界"
fmt.Println("Byte length:", len(s))
fmt.Println("Rune count:", utf8.RuneCountInString(s))
}
🔸Результат:
Byte length: 6
Rune count: 2
👍6
💬Какие риски возникают при использовании нескольких тегов полей в одной структуре?
📌Основная проблема при использовании нескольких тегов полей в одной структуре заключается в том, что это может привести к тесной связанности между различными слоями нашего приложения.
📌Простой пример:
🔸В примере у структуры Po
🔸При использовании подобных тегов слой HTTP-ответа (веб-сервер) и слой хранения (MongoDB) становятся тесно связанными. Если мы хотим изменить ti
📌Основная проблема при использовании нескольких тегов полей в одной структуре заключается в том, что это может привести к тесной связанности между различными слоями нашего приложения.
📌Простой пример:
type Post struct {
Title string `json:"title" bson:"title"`
SubTitle string `json:"subtitle" bson:"subtitle"`
}
🔸В примере у структуры Po
st д
ля каждого поля есть два тега поля: json и
bson.
Эти теги могут использоваться в разных целях, например, для отправки HTTP-ответов (используя json)
и обработки демаршализации MongoDB (используя bson).
🔸При использовании подобных тегов слой HTTP-ответа (веб-сервер) и слой хранения (MongoDB) становятся тесно связанными. Если мы хотим изменить ti
tle н
а, например, shortTitle,
нам нужно будет обновить и HTTP-ответ (что также может повлиять на клиентов, обрабатывающих ответ), и хранение в MongoDB.👍1
🧑💻 Статьи для IT: как объяснять и распространять значимые идеи
Напоминаем, что у нас есть бесплатный курс для всех, кто хочет научиться интересно писать — о программировании и в целом.
Что: семь модулей, посвященных написанию, редактированию, иллюстрированию и распространению публикаций.
Для кого: для авторов, копирайтеров и просто программистов, которые хотят научиться интересно рассказывать о своих проектах.
👉Материалы регулярно дополняются, обновляются и корректируются. А еще мы отвечаем на все учебные вопросы в комментариях курса.
Напоминаем, что у нас есть бесплатный курс для всех, кто хочет научиться интересно писать — о программировании и в целом.
Что: семь модулей, посвященных написанию, редактированию, иллюстрированию и распространению публикаций.
Для кого: для авторов, копирайтеров и просто программистов, которые хотят научиться интересно рассказывать о своих проектах.
👉Материалы регулярно дополняются, обновляются и корректируются. А еще мы отвечаем на все учебные вопросы в комментариях курса.
💬Где полезен встроенный метод recover в Go?
Встроенный метод
// Плохо
func main() {
defer recover()
panicCode()
}
// Лучше
📌Кроме того:
🔸Обработка ошибок: в ситуациях, когда паника является возможной и ожидаемой, например, при работе с внешними ресурсами или библиотеками, которые могут вызывать панику, re
🔸Неотложное восстановление: в демонизированных приложениях или долго работающих процессах, где стабильность имеет критическое значение, re
🔸Откат транзакций: в операциях, которые должны быть атомарными, таких как обновления базы данных, re
🔸Логирование и отладка: re
Встроенный метод
recover
действительно полезен в отложенных функциях, но не рекомендуется вызывать его напрямую с помощью ключевого слова defer
.// Плохо
func main() {
defer recover()
panicCode()
}
// Лучше
func handlePanic() {
if panicInfo := recover(); panicInfo != nil {
fmt.Println(panicInfo)
}
}
func main() {
defer handlePanic()
panicCode()
}
📌Кроме того:
🔸Обработка ошибок: в ситуациях, когда паника является возможной и ожидаемой, например, при работе с внешними ресурсами или библиотеками, которые могут вызывать панику, re
cover м
ожет быть использован для возврата ошибки вместо завершения программы.🔸Неотложное восстановление: в демонизированных приложениях или долго работающих процессах, где стабильность имеет критическое значение, re
cover м
ожет использоваться для обеспечения того, чтобы временная ошибка не привела к полному сбою системы.🔸Откат транзакций: в операциях, которые должны быть атомарными, таких как обновления базы данных, re
cover м
ожет использоваться для обнаружения паники и выполнения отката транзакции, чтобы поддерживать целостность данных.🔸Логирование и отладка: re
cover м
ожет использоваться для перехвата паники, логирования диагностической информации и затем повторного вызова паники, чтобы стандартный процесс обработки ошибок мог продолжить работу.❤8👍1
💬Для чего в Go предназначена директива "//go:embed"
📌Начиная с Go 1.16, директива
📌Во время выполнения, эти ресурсы становятся доступны через переменную, к которой применяется директива. Нам не нужно заботиться о механизмах пути к файлу или открытии и чтении файлов во время выполнения, что упрощает распространение программ, требующих доступа к внешним файлам.
Простой пример:
Все файлы в директории static встраиваются в бинарный файл. Директива //
Этот функционал особенно полезен, когда мы хотим создать самодостаточное приложение, которое не зависит от внешних файлов во время выполнения.
👉 Подробнее
?
📌Начиная с Go 1.16, директива
//go:embed
представляет собой специальный комментарий, который используется для встраивания файлов и директорий непосредственно в скомпилированный бинарный файл Go.📌Во время выполнения, эти ресурсы становятся доступны через переменную, к которой применяется директива. Нам не нужно заботиться о механизмах пути к файлу или открытии и чтении файлов во время выполнения, что упрощает распространение программ, требующих доступа к внешним файлам.
Простой пример:
package main
import (
"embed"
"io/fs"
"net/http"
)
//go:embed static/*
var staticFiles embed.FS
func main() {
// Используем встроенные файлы напрямую
http.Handle("/", http.FileServer(http.FS(staticFiles)))
http.ListenAndServe(":8080", nil)
}
Все файлы в директории static встраиваются в бинарный файл. Директива //
go:embed д
олжна быть расположена непосредственно перед объявлением переменной без пустых строк между комментарием и объявлением. Это позволяет использовать staticFiles к
ак файловую систему внутри Go-кода.Этот функционал особенно полезен, когда мы хотим создать самодостаточное приложение, которое не зависит от внешних файлов во время выполнения.
👉 Подробнее
👍13🔥2