💬Go — язык программирования, который отлично подходит для разработки облачных приложений. Что облачные технологии и облачные приложения из себя представляют теоретически?
📌Так звучат определения по мнению Cloud Native Computing Foundation:
• Облачные технологии позволяют создавать и запускать масштабируемые приложения в современных динамических окружениях — общедоступных, частных и гибридных облаках.
• Облачные технологии делают слабосвязанные системы устойчивыми, управляемыми и наблюдаемыми. В сочетании с надежной автоматизацией они позволяют разработчикам часто и предсказуемо вносить важные изменения с минимальными усилиями.
📝Исходя из этого, облачные приложения — больше, чем просто приложения, которые работают в облаке. Они также должны отвечать некоторым требованиям/атрибутам:
👉Масштабируемость — способность показывать ожидаемое поведение в условиях значительных колебаний спроса вверх и вниз.
👉Слабая связанность — свойство системы и стратегия проектирования, согласно которой компоненты системы знают лишь самый минимум о любых других компонентах.
👉Устойчивость — способность системы восстанавливаться после ошибок и сбоев.
👉Управляемость — простота (или ее отсутствие), с которой можно изменить поведение системы для обеспечения безопасности, бесперебойной работы и соответствия меняющимся требованиям.
👉Наблюдаемость — способность определения внутреннего состояния системы по наблюдаемым результатам.
📌Так звучат определения по мнению Cloud Native Computing Foundation:
• Облачные технологии позволяют создавать и запускать масштабируемые приложения в современных динамических окружениях — общедоступных, частных и гибридных облаках.
• Облачные технологии делают слабосвязанные системы устойчивыми, управляемыми и наблюдаемыми. В сочетании с надежной автоматизацией они позволяют разработчикам часто и предсказуемо вносить важные изменения с минимальными усилиями.
📝Исходя из этого, облачные приложения — больше, чем просто приложения, которые работают в облаке. Они также должны отвечать некоторым требованиям/атрибутам:
👉Масштабируемость — способность показывать ожидаемое поведение в условиях значительных колебаний спроса вверх и вниз.
👉Слабая связанность — свойство системы и стратегия проектирования, согласно которой компоненты системы знают лишь самый минимум о любых других компонентах.
👉Устойчивость — способность системы восстанавливаться после ошибок и сбоев.
👉Управляемость — простота (или ее отсутствие), с которой можно изменить поведение системы для обеспечения безопасности, бесперебойной работы и соответствия меняющимся требованиям.
👉Наблюдаемость — способность определения внутреннего состояния системы по наблюдаемым результатам.
👍9
💬 Что такое data race (гонка данных) в контексте Go?
📌Гонки данных — одни из наиболее распространенных и самых сложных для отладки типов ошибок в конкурентных системах. Гонка данных возникает, когда две горутины одновременно обращаются к одной и той же переменной, и хотя бы одно из обращений — запись. Чтобы избежать эту проблемы, в Go предоставляются различные примитивы синхронизации.
📌Race Condition (состояние гонки) — более широкое понятие, чем гонка данных. Оно описывает ситуацию, когда поведение программы зависит от относительного порядка выполнения операций. Гонка данных — один из видов состояний гонки, но не единственный.
Пример гонки данных, которая может привести к сбоям и повреждению памяти:
📌Гонки данных — одни из наиболее распространенных и самых сложных для отладки типов ошибок в конкурентных системах. Гонка данных возникает, когда две горутины одновременно обращаются к одной и той же переменной, и хотя бы одно из обращений — запись. Чтобы избежать эту проблемы, в Go предоставляются различные примитивы синхронизации.
📌Race Condition (состояние гонки) — более широкое понятие, чем гонка данных. Оно описывает ситуацию, когда поведение программы зависит от относительного порядка выполнения операций. Гонка данных — один из видов состояний гонки, но не единственный.
Пример гонки данных, которая может привести к сбоям и повреждению памяти:
func main() {
c := make(chan bool)
m := make(map[string]string)
go func() {
m["1"] = "a" //
Первый конфликтный доступ
c <- true
}()
m["2"] = "b" //
Второй конфликтный доступ <-c
for k, v := range m {
fmt.Println(k, v)
}
}
❗️Чтобы помочь диагностировать такие ошибки, Go включает встроенный детектор гонок данных. Для его использования добавьте флаг -race
в команду go:
$ go test -race mypkg
$ go run -race mysrc.go
$ go build -race mycmd
$ go install -race mypkg
📌Переменная окружения GORACE
устанавливает параметры детектора гонок данных, например:
$ GORACE="log_path=/tmp/race/report Strip_path_prefix=/my/go/sources/" go test -race
👉 Подробнее🔥7👍4
💬Что из себя представляет пустой идентификатор в контексте языка Go?
📌Пустой идентификатор "
👉Несколько примеров:
1. Игнорирование возвращаемых значений функции: когда функция возвращает несколько значений, но нам нужно только одно или несколько из них.
2. Игнорирование элементов в range: когда перебираются элементы среза или типа map, и нам нужен только ключ или только значение.
3. Импортирование пакета: когда нужно импортировать пакет только для того, чтобы выполнить инициализацию, определенную в нем, без использования его функций или типов.
4. Игнорирование переменных в множественном присваивании:
5. Игнорирование ошибок. Хотя так делать не рекомендуется, пустой идентификатор можно использовать для игнорирования ошибок.
6. Использование в анонимных структурах: когда создается анонимная структура, и нам не нужно давать имя одному из ее полей.
☝️Пустой идентификатор является полезным инструментом в Go и его можно безопасно использовать на практике, но злоупотреблять им точно не стоит, особенно когда речь идет об игнорировании ошибок.
📌Пустой идентификатор "
_
" в Go действует как своего рода анонимный заполнитель. Его можно использовать как любой другой идентификатор в объявлении, но с ним не будет связано никакое значение.👉Несколько примеров:
1. Игнорирование возвращаемых значений функции: когда функция возвращает несколько значений, но нам нужно только одно или несколько из них.
value, _ := someFunction()
2. Игнорирование элементов в range: когда перебираются элементы среза или типа map, и нам нужен только ключ или только значение.
for k, _ := range myMap {
fmt.Println(k)
}
for _, v := range mySlice {
fmt.Println(v)
}
3. Импортирование пакета: когда нужно импортировать пакет только для того, чтобы выполнить инициализацию, определенную в нем, без использования его функций или типов.
import _ "image/png"
4. Игнорирование переменных в множественном присваивании:
_, y := getCoordinates()
5. Игнорирование ошибок. Хотя так делать не рекомендуется, пустой идентификатор можно использовать для игнорирования ошибок.
result, _ := strconv.Atoi("123")
6. Использование в анонимных структурах: когда создается анонимная структура, и нам не нужно давать имя одному из ее полей.
person := struct {
Name string
_ int
}{"Alice", 30}
☝️Пустой идентификатор является полезным инструментом в Go и его можно безопасно использовать на практике, но злоупотреблять им точно не стоит, особенно когда речь идет об игнорировании ошибок.
👍9🔥3
💬Что из себя представляют анонимные функции и замыкания в Go?
🔸Функции в Go — обычные значения, с которыми можно работать так же, как с любыми другими объектами: они имеют типы, их можно присваивать переменным и даже передавать и возвращать другим функциям.
🔸Функции могут создаваться внутри других функций как анонимные функции, которые можно вызывать, передавать или использовать иным способом как любые другие функции. Анонимная функция — функция, которой не назначено имя.
🔸Особенностью Go является доступность состояния внешней функции из анонимных функций, даже после ее завершения. Фактически это позволяет определять замыкания. Замыкание — вложенная функция, сохраняющая доступ к переменным внешней функции даже после завершения последней.
📌Возьмем функцию incrementor. Она имеет состояние в виде переменной i и возвращает анонимную функцию, которая увеличивает значение перед возвратом. Можно сказать, что возвращаемая функция «замкнута» на переменной i.
📌Вызов incrementor создаст свою локальную копию i и вернет новую анонимную функцию, увеличивающую значение этой копии. Последующие вызовы incrementor будут создавать новые копии i:
🔸Функции в Go — обычные значения, с которыми можно работать так же, как с любыми другими объектами: они имеют типы, их можно присваивать переменным и даже передавать и возвращать другим функциям.
🔸Функции могут создаваться внутри других функций как анонимные функции, которые можно вызывать, передавать или использовать иным способом как любые другие функции. Анонимная функция — функция, которой не назначено имя.
🔸Особенностью Go является доступность состояния внешней функции из анонимных функций, даже после ее завершения. Фактически это позволяет определять замыкания. Замыкание — вложенная функция, сохраняющая доступ к переменным внешней функции даже после завершения последней.
📌Возьмем функцию incrementor. Она имеет состояние в виде переменной i и возвращает анонимную функцию, которая увеличивает значение перед возвратом. Можно сказать, что возвращаемая функция «замкнута» на переменной i.
func incrementer() func() int {
i := 0
return func() int {
i++
return i
}
}
📌Вызов incrementor создаст свою локальную копию i и вернет новую анонимную функцию, увеличивающую значение этой копии. Последующие вызовы incrementor будут создавать новые копии i:
func main() {
increment := incrementer()
fmt.Println(increment())
// 1
fmt.Println(increment())
// 2
fmt.Println(increment())
// 3
newIncrement := incrementer()
fmt.Println(newIncrement())
// 1
}
🔥16👍1
💬Как проверить тип переменной во время выполнения программы в Go?
📌Оператор switch — лучший способ проверить тип переменной во время выполнения. Каждый switch содержит по крайней мере один оператор case, который действует как условный оператор, и default case, который выполняется, если ни один из блоков case не является истинным.
👉 Например, мы можем создать swich, который проверяет, содержит ли значение интерфейса i тип int или string:
👉 Результат:
Double 21 is 42
"hello" is 5 bytes long
I don't know type bool!
📌Оператор switch — лучший способ проверить тип переменной во время выполнения. Каждый switch содержит по крайней мере один оператор case, который действует как условный оператор, и default case, который выполняется, если ни один из блоков case не является истинным.
👉 Например, мы можем создать swich, который проверяет, содержит ли значение интерфейса i тип int или string:
func do(i interface{}) {
switch v := i.(type) {
case int:
fmt.Printf("Double %v is %v\n", v, v*2)
case string:
fmt.Printf("%q is %v bytes long\n", v, len(v))
default:
fmt.Printf("I don't know type %T!\n", v)
}
}
func main() {
do(21)
do("hello")
do(true)
}
👉 Результат:
Double 21 is 42
"hello" is 5 bytes long
I don't know type bool!
👍9
💬Что такое стек и как его реализовать с помощью Go?
📌Стек — тип данных, представляющий собой список элементов, организованных по принципу LIFO (last in — first out, «последним пришёл — первым вышел»).
📌Стек хранит последовательность данных. Связаны данные так: каждый элемент указывает на тот, который нужно использовать следующим. Это линейная связь — данные идут друг за другом и нужно брать их по очереди. Из середины стека брать нельзя.
📌Главный принцип работы стека — данные, которые попали в стек недавно, используются первыми. Чем раньше попал — тем позже используется. После использования элемент стека исчезает, и верхним становится следующий элемент.
📌Три основные операции над стеком:
🔸push — добавление элемента
🔸pop — удаление верхнего элемента
🔸peek — возвращение последнего элемента, не удаляя его.
👉 В Go стек можно реализовать с помощью среза:
Мы использовали срез для хранения элементов стека. Метод
📌Стек — тип данных, представляющий собой список элементов, организованных по принципу LIFO (last in — first out, «последним пришёл — первым вышел»).
📌Стек хранит последовательность данных. Связаны данные так: каждый элемент указывает на тот, который нужно использовать следующим. Это линейная связь — данные идут друг за другом и нужно брать их по очереди. Из середины стека брать нельзя.
📌Главный принцип работы стека — данные, которые попали в стек недавно, используются первыми. Чем раньше попал — тем позже используется. После использования элемент стека исчезает, и верхним становится следующий элемент.
📌Три основные операции над стеком:
🔸push — добавление элемента
🔸pop — удаление верхнего элемента
🔸peek — возвращение последнего элемента, не удаляя его.
👉 В Go стек можно реализовать с помощью среза:
type Stack struct {
items []int
}
func (s *Stack) Push(item int) {
s.items = append(s.items, item)
}
func (s *Stack) Pop() int {
if len(s.items) == 0 {
panic("Stack is empty!")
}
item := s.items[len(s.items)-1]
s.items = s.items[:len(s.items)-1]
return item
}
func (s *Stack) Peek() int {
if len(s.items) == 0 {
panic("Stack is empty!")
}
return s.items[len(s.items)-1]
}
func (s *Stack) IsEmpty() bool {
return len(s.items) == 0
}
func (s *Stack) Size() int {
return len(s.items)
}
Мы использовали срез для хранения элементов стека. Метод
Push
добавляет элемент на верх стека, метод Pop
извлекает его, а метод Peek
позволяет посмотреть верхний элемент без его извлечения. Также мы использовали проверку стека на наличие элементов.👍11
🧑💻 Статьи для IT: как объяснять и распространять значимые идеи
Напоминаем, что у нас есть бесплатный курс для всех, кто хочет научиться интересно писать — о программировании и в целом.
Что: семь модулей, посвященных написанию, редактированию, иллюстрированию и распространению публикаций.
Для кого: для авторов, копирайтеров и просто программистов, которые хотят научиться интересно рассказывать о своих проектах.
👉Материалы регулярно дополняются, обновляются и корректируются. А еще мы отвечаем на все учебные вопросы в комментариях курса.
Напоминаем, что у нас есть бесплатный курс для всех, кто хочет научиться интересно писать — о программировании и в целом.
Что: семь модулей, посвященных написанию, редактированию, иллюстрированию и распространению публикаций.
Для кого: для авторов, копирайтеров и просто программистов, которые хотят научиться интересно рассказывать о своих проектах.
👉Материалы регулярно дополняются, обновляются и корректируются. А еще мы отвечаем на все учебные вопросы в комментариях курса.
💬Как поменять местами значения двух переменных без временной переменной? Очень простой вопрос, который может быть задан на собесе.
1️⃣Пример с использованием сложения и вычитания:
Таким образом,
2️⃣Пример с использованием XOR (исключающего ИЛИ):
Когда мы применяем XOR дважды с теми же числами, мы получаем исходное значение переменной, что позволяет нам поменять значения без использования временной переменной.
3️⃣Пример с реализацией простой функции
1️⃣Пример с использованием сложения и вычитания:
a := 5
b := 3
a = a + b
// a становится 8b = a - b
// b становится 5 a = a - b
// a становится 3Таким образом,
a
и b
меняются значениями без использования временной переменной.2️⃣Пример с использованием XOR (исключающего ИЛИ):
a := 5
// 0101 в двоичной системеb := 3
// 0011 в двоичной системеa = a ^ b
// a становится 6 (0110)b = a ^ b
// b становится 5 (0101)a = a ^ b
// a становится 3 (0011)Когда мы применяем XOR дважды с теми же числами, мы получаем исходное значение переменной, что позволяет нам поменять значения без использования временной переменной.
3️⃣Пример с реализацией простой функции
func main() {
fmt.Println(swap())
}
func swap() []int {
a, b := 15, 10
b, a = a, b
return []int{a, b}
}
👍14👏3
💬Реализуйте функцию, которая принимает срез целых чисел и переворачивает его без использования временного среза.
📌Простой, но достаточно эффективный способ:
// [1 2 3]
📌Другой способ с использованием рекурсивного метода: рекурсивно меняем местами первый и последний элементы, затем второй и предпоследний и так далее.
// [1 2 3]
📌Простой, но достаточно эффективный способ:
func reverse(sw []int) {
for a, b := 0, len(sw)-1; a < b; a, b = a+1, b-1 {
sw[a], sw[b] = sw[b], sw[a]
}
}
func main() {
x := []int{3, 2, 1}
reverse(x)
fmt.Println(x)
}
// [1 2 3]
📌Другой способ с использованием рекурсивного метода: рекурсивно меняем местами первый и последний элементы, затем второй и предпоследний и так далее.
func reverseRecursive(sw []int, start, end int) {
if start >= end {
return
}
sw[start], sw[end] = sw[end], sw[start]
reverseRecursive(sw, start+1, end-1)
}
func main() {
x := []int{3, 2, 1}
reverseRecursive(x, 0, len(x)-1)
fmt.Println(x)
}
// [1 2 3]
👍4
Самые полезные каналы для программистов в одной подборке!
Сохраняйте себе, чтобы не потерять 💾
🔥Для всех
Библиотека программиста — новости, статьи, досуг, фундаментальные темы
Книги для программистов
IT-мемы
Proglib Academy — тут мы рассказываем про обучение и курсы
🐘PHP
Библиотека пхпшника
Вакансии по PHP, Symfony, Laravel
Библиотека PHP для собеса — тренируемся отвечать на каверзные вопросы во время интервью и технического собеседования
Библиотека задач по PHP — код, квизы и тесты
🐍Python
Библиотека питониста
Вакансии по питону, Django, Flask
Библиотека Python для собеса — тренируемся отвечать на каверзные вопросы во время интервью и технического собеседования
Библиотека задач по Python — код, квизы и тесты
☕Java
Библиотека джависта — полезные статьи по Java, новости и обучающие материалы
Библиотека Java для собеса — тренируемся отвечать на каверзные вопросы во время интервью и технического собеседования
Библиотека задач по Java — код, квизы и тесты
Вакансии для java-разработчиков
👾Data Science
Библиотека Data Science — полезные статьи, новости и обучающие материалы
Библиотека Data Science для собеса — тренируемся отвечать на каверзные вопросы во время интервью и технического собеседования
Библиотека задач по Data Science — код, квизы и тесты
Вакансии по Data Science, анализу данных, аналитике, искусственному интеллекту
🦫Go
Библиотека Go разработчика — полезные статьи, новости и обучающие материалы по Go
Библиотека Go для собеса — тренируемся отвечать на каверзные вопросы во время интервью и технического собеседования
Библиотека задач по Go — код, квизы и тесты
Вакансии по Go
🧠C++
Библиотека C/C++ разработчика — полезные статьи, новости и обучающие материалы по C++
Библиотека C++ для собеса — тренируемся отвечать на каверзные вопросы во время интервью и технического собеседования
Библиотека задач по C++ — код, квизы и тесты
Вакансии по C++
💻Другие профильные каналы
Библиотека фронтендера
Библиотека шарписта
Библиотека мобильного разработчика
Библиотека хакера
Библиотека devops’a
Библиотека тестировщика
💼Каналы с вакансиями
Вакансии по фронтенду, джаваскрипт, React, Angular, Vue
Вакансии по C#, .NET, Unity Вакансии по PHP, Symfony, Laravel
Вакансии по DevOps & SRE
Вакансии для мобильных разработчиков
Вакансии по QA тестированию
InfoSec Jobs — вакансии по информационной безопасности
📁Чтобы добавить папку с нашими каналами, нажмите 👉сюда👈
🤖Также у нас есть боты:
Бот с IT-вакансиями
Бот с мероприятиями в сфере IT
Мы в других соцсетях:
🔸VK
🔸YouTube
🔸Дзен
🔸Facebook
🔸Instagram
Сохраняйте себе, чтобы не потерять 💾
🔥Для всех
Библиотека программиста — новости, статьи, досуг, фундаментальные темы
Книги для программистов
IT-мемы
Proglib Academy — тут мы рассказываем про обучение и курсы
🐘PHP
Библиотека пхпшника
Вакансии по PHP, Symfony, Laravel
Библиотека PHP для собеса — тренируемся отвечать на каверзные вопросы во время интервью и технического собеседования
Библиотека задач по PHP — код, квизы и тесты
🐍Python
Библиотека питониста
Вакансии по питону, Django, Flask
Библиотека Python для собеса — тренируемся отвечать на каверзные вопросы во время интервью и технического собеседования
Библиотека задач по Python — код, квизы и тесты
☕Java
Библиотека джависта — полезные статьи по Java, новости и обучающие материалы
Библиотека Java для собеса — тренируемся отвечать на каверзные вопросы во время интервью и технического собеседования
Библиотека задач по Java — код, квизы и тесты
Вакансии для java-разработчиков
👾Data Science
Библиотека Data Science — полезные статьи, новости и обучающие материалы
Библиотека Data Science для собеса — тренируемся отвечать на каверзные вопросы во время интервью и технического собеседования
Библиотека задач по Data Science — код, квизы и тесты
Вакансии по Data Science, анализу данных, аналитике, искусственному интеллекту
🦫Go
Библиотека Go разработчика — полезные статьи, новости и обучающие материалы по Go
Библиотека Go для собеса — тренируемся отвечать на каверзные вопросы во время интервью и технического собеседования
Библиотека задач по Go — код, квизы и тесты
Вакансии по Go
🧠C++
Библиотека C/C++ разработчика — полезные статьи, новости и обучающие материалы по C++
Библиотека C++ для собеса — тренируемся отвечать на каверзные вопросы во время интервью и технического собеседования
Библиотека задач по C++ — код, квизы и тесты
Вакансии по C++
💻Другие профильные каналы
Библиотека фронтендера
Библиотека шарписта
Библиотека мобильного разработчика
Библиотека хакера
Библиотека devops’a
Библиотека тестировщика
💼Каналы с вакансиями
Вакансии по фронтенду, джаваскрипт, React, Angular, Vue
Вакансии по C#, .NET, Unity Вакансии по PHP, Symfony, Laravel
Вакансии по DevOps & SRE
Вакансии для мобильных разработчиков
Вакансии по QA тестированию
InfoSec Jobs — вакансии по информационной безопасности
📁Чтобы добавить папку с нашими каналами, нажмите 👉сюда👈
🤖Также у нас есть боты:
Бот с IT-вакансиями
Бот с мероприятиями в сфере IT
Мы в других соцсетях:
🔸VK
🔸YouTube
🔸Дзен
👍1
💬Что из себя представляет пакет cgo и для чего он предназначен?
📌Cgo позволяет создавать пакеты Go, вызывающие код на C. С его помощью мы можем вызывать функции C напрямую из кода на Go и наоборот.
📌Это полезно, когда у нас есть библиотеки на C, которые мы хотим использовать в Go-проекте, или когда нам требуется взаимодействовать с системными вызовами на более низком уровне.
📌Основные особенности cgo:
1. Позволяет встраивать код на C прямо в исходники Go.
2. Автоматически обрабатывает преобразования типов между Go и C.
3. Важно быть осторожным с управлением памятью, так как Go имеет сборщик мусора, а C — нет.
📌Рассмотрим простой пример
• Пакет
• Пакет
• Функция
• Если импорту "C" сразу предшествует комментарий, этот комментарий, называемый преамбулой, используется в качестве заголовка при компиляции частей пакета C. Преамбула может содержать любой код на C, включая объявления и определения функций и переменных. Затем они могут быть переданы из кода Go, как если бы они были определены в пакете "C". Могут использоваться все имена, объявленные в преамбуле, даже если они начинаются со строчной буквы.
👉 Подробнее
📌Cgo позволяет создавать пакеты Go, вызывающие код на C. С его помощью мы можем вызывать функции C напрямую из кода на Go и наоборот.
📌Это полезно, когда у нас есть библиотеки на C, которые мы хотим использовать в Go-проекте, или когда нам требуется взаимодействовать с системными вызовами на более низком уровне.
📌Основные особенности cgo:
1. Позволяет встраивать код на C прямо в исходники Go.
2. Автоматически обрабатывает преобразования типов между Go и C.
3. Важно быть осторожным с управлением памятью, так как Go имеет сборщик мусора, а C — нет.
📌Рассмотрим простой пример
package rand
/*
#include <stdlib.h>
*/
import "C"
func Random() int {
return int(C.random())
}
func Seed(i int) {
C.srandom(C.uint(i))
}
• Пакет
rand
импортирует "C", где "C" — это «псевдопакет», специальное имя, интерпретируемое cgo как ссылка на пространство имен C.• Пакет
rand
содержит четыре ссылки на пакет C: вызовы C.random
и C.srandom
, преобразование C.uint(i)
и оператор импорта. Функция Random
вызывает функцию random
стандартной библиотеки C и возвращает результат. В C функция random
возвращает значение типа C long, которое cgo представляет как тип C.long
. Его нужно преобразовать в тип Go, прежде чем он сможет быть использован кодом Go за пределами этого пакета, используя обычное преобразование типов Go.• Функция
Seed
делает обратное. Она принимает обычный Go int
, преобразует его в тип C unsigned int
и передает его функции C srandom
.• Если импорту "C" сразу предшествует комментарий, этот комментарий, называемый преамбулой, используется в качестве заголовка при компиляции частей пакета C. Преамбула может содержать любой код на C, включая объявления и определения функций и переменных. Затем они могут быть переданы из кода Go, как если бы они были определены в пакете "C". Могут использоваться все имена, объявленные в преамбуле, даже если они начинаются со строчной буквы.
👉 Подробнее
go.dev
C? Go? Cgo! - The Go Programming Language
How to use cgo to let Go packages call C code.
❤6👍5
💬Go — императивный или декларативный? В чем разница между двумя подходами?
📌Go является императивным ЯП. Разница между императивными и декларативными языками программирования заключается в подходе к описанию того, как и что программа должна делать:
1️⃣Императивный подход: в императивных ЯП мы описываем, как решить задачу, шаг за шагом. Мы предоставляем последовательность команд/инструкций для достижения определенного результата.
📌Характерные черты:
• В исходном коде программы записываются инструкции (команды).
• Инструкции должны выполняться последовательно.
• Данные, получаемые при выполнении предыдущих инструкций, могут читаться из памяти последующими инструкциями.
• Данные, полученные при выполнении инструкции, могут записываться в память.
2️⃣ Декларативный подход: в декларативных ЯП мы описываем, что хотим получить, но не указываем конкретные шаги, как это сделать. Вместо этого система или интерпретатор решает, как лучше достичь желаемого результата. Примеры декларативных языков или технологий включают SQL (для запросов к базам данных) и HTML (для описания структуры веб-страниц).
📌Go является императивным ЯП. Разница между императивными и декларативными языками программирования заключается в подходе к описанию того, как и что программа должна делать:
1️⃣Императивный подход: в императивных ЯП мы описываем, как решить задачу, шаг за шагом. Мы предоставляем последовательность команд/инструкций для достижения определенного результата.
📌Характерные черты:
• В исходном коде программы записываются инструкции (команды).
• Инструкции должны выполняться последовательно.
• Данные, получаемые при выполнении предыдущих инструкций, могут читаться из памяти последующими инструкциями.
• Данные, полученные при выполнении инструкции, могут записываться в память.
2️⃣ Декларативный подход: в декларативных ЯП мы описываем, что хотим получить, но не указываем конкретные шаги, как это сделать. Вместо этого система или интерпретатор решает, как лучше достичь желаемого результата. Примеры декларативных языков или технологий включают SQL (для запросов к базам данных) и HTML (для описания структуры веб-страниц).
👍8
💬Каким будет результат при различных операциях (чтение, запись и закрытие) и состояниях канала?
Сегодняшний ответ будет таким👇
Сегодняшний ответ будет таким
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Command.png
375.7 KB
💬Что из себя представляет паттерн «Команда» и как его реализовать на Go?
📌Команда — это поведенческий паттерн, позволяющий заворачивать запросы или простые операции в отдельные объекты.
Это позволяет откладывать выполнение команд, выстраивать их в очереди, а также хранить историю и делать отмену.
❗️ В описании паттерна применяются общие понятия, такие как Класс, Объект, Абстрактный класс. Применимо к Go, это Пользовательский Тип, Значение этого Типа и Интерфейс. Также в Go вместо общепринятого наследования используется агрегирование и встраивание.
📌В паттерне Команда мы оперируем следующими понятиями:
• Command — запрос в виде объекта на выполнение
• Receiver — объект-получатель запроса, который будет обрабатывать нашу команду;
• Invoker — объект-инициатор запроса
📌Паттерн отделяет объект, инициирующий операцию, от объекта, который знает, как ее выполнить. Единственное, что должен знать инициатор, это как отправить команду.
📌Для реализации требуется:
1. Базовый абстрактный класс, описывающий интерфейс команды
2. Класс ConcreteCommand, реализующий команду
3. Класс Invoker, реализующий инициатора, записывающий команду и провоцирующий её выполнение
4. Класс Receiver, реализующий получателя и имеющий набор действий, которые команда может запрашивать
📌Invoker умеет складывать команды и инициировать их выполнение по какому-то событию. Обратившись к Invoker, можно отменить команду, пока она не выполнена.
📌ConcreteCommand содержит в себе запросы к Receiver, которые тот должен выполнять. В свою очередь Receiver содержит только набор действий (Actions), которые выполняются при обращении к ним из ConcreteCommand.
📌Команда — это поведенческий паттерн, позволяющий заворачивать запросы или простые операции в отдельные объекты.
Это позволяет откладывать выполнение команд, выстраивать их в очереди, а также хранить историю и делать отмену.
📌В паттерне Команда мы оперируем следующими понятиями:
• Command — запрос в виде объекта на выполнение
• Receiver — объект-получатель запроса, который будет обрабатывать нашу команду;
• Invoker — объект-инициатор запроса
📌Паттерн отделяет объект, инициирующий операцию, от объекта, который знает, как ее выполнить. Единственное, что должен знать инициатор, это как отправить команду.
📌Для реализации требуется:
1. Базовый абстрактный класс, описывающий интерфейс команды
2. Класс ConcreteCommand, реализующий команду
3. Класс Invoker, реализующий инициатора, записывающий команду и провоцирующий её выполнение
4. Класс Receiver, реализующий получателя и имеющий набор действий, которые команда может запрашивать
📌Invoker умеет складывать команды и инициировать их выполнение по какому-то событию. Обратившись к Invoker, можно отменить команду, пока она не выполнена.
📌ConcreteCommand содержит в себе запросы к Receiver, которые тот должен выполнять. В свою очередь Receiver содержит только набор действий (Actions), которые выполняются при обращении к ним из ConcreteCommand.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
💬В чем разница между поверхностным и глубоким копированием в Go?
📌Поверхностное копирование (shallow copy) означает создание новой переменной или структуры, которая ссылается на те же данные в памяти, что и исходная переменная/структура.
• Поверхностное копирование применимо, когда мы хотим использовать одни и те же данные, но с разными именами или переменными, и нам не важно, чтобы изменения в одной переменной влияли на другую.
📌Глубокое копирование (deep copy) подразумевает создание новой переменной или структуры, которая имеет собственные, полностью независимые копии данных, содержащихся в исходной переменной или структуре.
• Глубокое копирование может быть важно, например, при работе со сложными структурами данных, где изменение одного элемента может повлиять на целую структуру, а также при сериализации данных или создании копии структуры.
📌Поверхностное копирование (shallow copy) означает создание новой переменной или структуры, которая ссылается на те же данные в памяти, что и исходная переменная/структура.
• Поверхностное копирование применимо, когда мы хотим использовать одни и те же данные, но с разными именами или переменными, и нам не важно, чтобы изменения в одной переменной влияли на другую.
original := []int{1, 2, 3}
copied := original
copied[0] = 99
fmt.Println(original)
// [99 2 3]📌Глубокое копирование (deep copy) подразумевает создание новой переменной или структуры, которая имеет собственные, полностью независимые копии данных, содержащихся в исходной переменной или структуре.
• Глубокое копирование может быть важно, например, при работе со сложными структурами данных, где изменение одного элемента может повлиять на целую структуру, а также при сериализации данных или создании копии структуры.
import "github.com/mohae/deepcopy"
original := []int{1, 2, 3}
copied := deepcopy.Copy(original)
copied[0] = 99
fmt.Println(original)
// [1 2 3]👍9
💬Что из себя представляет middleware в контексте веб-разработки на Go?
📌Middleware представляет собой промежуточные обработчики, которые имеют возможность выполнять код, обрабатывать запросы и ответы в процессе выполнения HTTP-запросов и ответов перед тем, как они достигнут конечных обработчиков.
• Middleware можно использовать для различных целей, таких как аутентификация, авторизация, логирование, обработка ошибок и многое другое.
• В Go, middleware часто реализуется как функции, которые принимают и возвращают значения, соответствующие интерфейсу
• Это позволяет создавать цепочки middleware, которые можно легко комбинировать и повторно использовать в различных частях приложения.
• Например, может существовать middleware для аутентификации пользователей, которое проверяет наличие действительного токена в заголовке HTTP-запроса перед тем, как передать управление следующему обработчику в цепочке. Если токен отсутствует или недействителен, middleware может вернуть ответ с ошибкой, не передавая управление дальше.
• В Go существует несколько популярных библиотек и фреймворков, которые предлагают встроенные или легко интегрируемые решения для создания и управления middleware, такие как Gorilla Mux, Gin или Echo.
📌Подробнее:
👉 Разработка REST-серверов на Go. Часть 5: Middleware
👉 HTTP Middleware
👉 Учимся разрабатывать REST API на Go на примере сокращателя ссылок
📌Middleware представляет собой промежуточные обработчики, которые имеют возможность выполнять код, обрабатывать запросы и ответы в процессе выполнения HTTP-запросов и ответов перед тем, как они достигнут конечных обработчиков.
• Middleware можно использовать для различных целей, таких как аутентификация, авторизация, логирование, обработка ошибок и многое другое.
• В Go, middleware часто реализуется как функции, которые принимают и возвращают значения, соответствующие интерфейсу
http.Handler
или http.HandlerFunc
. • Это позволяет создавать цепочки middleware, которые можно легко комбинировать и повторно использовать в различных частях приложения.
• Например, может существовать middleware для аутентификации пользователей, которое проверяет наличие действительного токена в заголовке HTTP-запроса перед тем, как передать управление следующему обработчику в цепочке. Если токен отсутствует или недействителен, middleware может вернуть ответ с ошибкой, не передавая управление дальше.
• В Go существует несколько популярных библиотек и фреймворков, которые предлагают встроенные или легко интегрируемые решения для создания и управления middleware, такие как Gorilla Mux, Gin или Echo.
📌Подробнее:
Please open Telegram to view this post
VIEW IN TELEGRAM
Хабр
Разработка REST-серверов на Go. Часть 5: Middleware
Это — пятый материал из серии статей , посвящённой разработке REST-серверов на Go. Здесь мы поговорим о middleware. У меня есть материал , посвящённый жизненному циклу HTTP-запросов в серверах,...
👍9
💬Какие операторы есть в языке Go? Назовите основные.
📌Арифметические:
• + : сложение
• - : вычитание
• * : умножение
• / : деление
• % : остаток от деления
• ++ : инкремент
• -- : декремент
📌Сравнительные:
• == : равно
• != : не равно
• < : меньше
• <= : меньше или равно
• > : больше
• >= : больше или равно
📌Логические:
• && : логическое И (AND)
• || : логическое ИЛИ (OR)
• ! : логическое НЕ (NOT)
📌Битовые:
• & : битовое И (AND)
• | : битовое ИЛИ (OR)
• ^ : битовое исключающее ИЛИ (XOR)
• &^ : битовая маска сброса (AND NOT)
• << : левый сдвиг
• >> : правый сдвиг
📌Операторы:
• = : присваивание
• +=, -=, *=, /=, %= : присваивание с операцией
• &=, |=, ^=, <<=, >>=, &^= : битовое присваивание с операцией
📌Прочие:
• & : оператор получения адреса
• * : оператор разыменования указателя
• <- : оператор канала (используется для отправки и получения данных через каналы)
• := : присваивание, используемое для объявления и инициализации переменной
📌Арифметические:
• + : сложение
• - : вычитание
• * : умножение
• / : деление
• % : остаток от деления
• ++ : инкремент
• -- : декремент
📌Сравнительные:
• == : равно
• != : не равно
• < : меньше
• <= : меньше или равно
• > : больше
• >= : больше или равно
📌Логические:
• && : логическое И (AND)
• || : логическое ИЛИ (OR)
• ! : логическое НЕ (NOT)
📌Битовые:
• & : битовое И (AND)
• | : битовое ИЛИ (OR)
• ^ : битовое исключающее ИЛИ (XOR)
• &^ : битовая маска сброса (AND NOT)
• << : левый сдвиг
• >> : правый сдвиг
📌Операторы:
• = : присваивание
• +=, -=, *=, /=, %= : присваивание с операцией
• &=, |=, ^=, <<=, >>=, &^= : битовое присваивание с операцией
📌Прочие:
• & : оператор получения адреса
• * : оператор разыменования указателя
• <- : оператор канала (используется для отправки и получения данных через каналы)
• := : присваивание, используемое для объявления и инициализации переменной
❤10👍5
💬Что из себя представляют Go workspaces?
🔸В версии Go 1.18 был введен новый режим workspace, который позволяет работать с несколькими модулями одновременно без необходимости редактирования
🔸В каждом workspace, модули рассматриваются как основные модули при разрешении зависимостей. До введения этой функции, для добавления функции в один модуль и ее использования в другом модуле, требовалось либо публиковать изменения первого модуля, либо редактировать файл
🔸Режим workspace в Go 1.18 решает ряд проблем, в частности, устраняет необходимость полагаться на локальные замены модулей. Вместо этого, все зависимости контролируются с использованием файла
🔸Файл
🔸Для создания workspace используется команда
📌Основные преимущества:
1. Организация кода: workspaces позволяют группировать связанные модули Go в одном месте, что упрощает управление и организацию кода, особенно в больших проектах с множеством зависимостей и модулей.
2. Управление зависимостями: с помощью workspaces можно легко управлять зависимостями между модулями. Это упрощает обновление, замену или удаление зависимостей в ваших проектах.
3. Локальная разработка: workspaces облегчают локальную разработку, позволяя вам работать над множеством модулей одновременно без необходимости постоянно публиковать изменения в удаленные репозитории.
4. Совместимость с Go модулями: workspaces расширяют возможности Go модулей, добавляя поддержку для работы с несколькими модулями в рамках одного workspace, что делает управление модулями более гибким и удобным.
5. Улучшенный рабочий процесс: Go workspaces предлагают улучшенный рабочий процесс для разработчиков, делая процесс сборки и тестирования более простым и эффективным.
6. Простота и переносимость: создание workspace не требует дополнительных инструментов. Это также обеспечивает переносимость между различными окружениями разработки и командами.
👉 Подробнее
🔸В версии Go 1.18 был введен новый режим workspace, который позволяет работать с несколькими модулями одновременно без необходимости редактирования
go.mod
файлов для каждого модуля. 🔸В каждом workspace, модули рассматриваются как основные модули при разрешении зависимостей. До введения этой функции, для добавления функции в один модуль и ее использования в другом модуле, требовалось либо публиковать изменения первого модуля, либо редактировать файл
go.mod
зависимого модуля с директивой replace
для локальных, неопубликованных изменений модуля.🔸Режим workspace в Go 1.18 решает ряд проблем, в частности, устраняет необходимость полагаться на локальные замены модулей. Вместо этого, все зависимости контролируются с использованием файла
go.work
в корневой директории вашего workspace. 🔸Файл
go.work
содержит директивы use
и replace
, которые переопределяют индивидуальные файлы go.mod
, устраняя необходимость редактирования каждого файла go.mod
вручную.🔸Для создания workspace используется команда
go work init
с перечислением директорий модулей в качестве аргументов, разделенных пробелами. Workspace не обязан содержать модули, с которыми вы работаете. Команда init
создает файл go.work
, который перечисляет модули в workspace. Если вы запустите go work init
без аргументов, команда создаст пустой workspace.📌Основные преимущества:
1. Организация кода: workspaces позволяют группировать связанные модули Go в одном месте, что упрощает управление и организацию кода, особенно в больших проектах с множеством зависимостей и модулей.
2. Управление зависимостями: с помощью workspaces можно легко управлять зависимостями между модулями. Это упрощает обновление, замену или удаление зависимостей в ваших проектах.
3. Локальная разработка: workspaces облегчают локальную разработку, позволяя вам работать над множеством модулей одновременно без необходимости постоянно публиковать изменения в удаленные репозитории.
4. Совместимость с Go модулями: workspaces расширяют возможности Go модулей, добавляя поддержку для работы с несколькими модулями в рамках одного workspace, что делает управление модулями более гибким и удобным.
5. Улучшенный рабочий процесс: Go workspaces предлагают улучшенный рабочий процесс для разработчиков, делая процесс сборки и тестирования более простым и эффективным.
6. Простота и переносимость: создание workspace не требует дополнительных инструментов. Это также обеспечивает переносимость между различными окружениями разработки и командами.
👉 Подробнее
go.dev
Tutorial: Getting started with multi-module workspaces - The Go Programming Language
👍11🔥3🤔1
💬Для чего в программах на Go используются функции?
Функции в Go играют ключевую роль, предлагая способ организации кода, повторного использования логики и разделения задач на меньшие, управляемые компоненты. Они выполняют несколько важных задач:
1️⃣Модульность и организация кода: функции позволяют разбивать программу на меньшие блоки, улучшая читаемость и понимание кода. Это способствует созданию более структурированных и поддерживаемых программ.
2️⃣Повторное использование кода: после написания функции ее можно использовать многократно в разных частях программы или даже в разных программах. Это сокращает дублирование кода и упрощает обновления.
3️⃣Абстракция и инкапсуляция: функции позволяют абстрагироваться от деталей реализации, сосредоточив внимание на функциональности. Это улучшает понимание кода и уменьшает сложность. Кроме того, функции могут создавать границы, предотвращая воздействие изменений в одной части программы на другие.
4️⃣Тестирование: разбиение программы на функции упрощает процесс тестирования. Мы можем тестировать каждую функцию независимо, что делает обнаружение и устранение ошибок более эффективными.
5️⃣Разделение задач: функции позволяют разделять сложные задачи на меньшие подзадачи. Это делает разработку более систематической, позволяя решать проблемы последовательно и шаг за шагом.
Функции в Go играют ключевую роль, предлагая способ организации кода, повторного использования логики и разделения задач на меньшие, управляемые компоненты. Они выполняют несколько важных задач:
1️⃣Модульность и организация кода: функции позволяют разбивать программу на меньшие блоки, улучшая читаемость и понимание кода. Это способствует созданию более структурированных и поддерживаемых программ.
2️⃣Повторное использование кода: после написания функции ее можно использовать многократно в разных частях программы или даже в разных программах. Это сокращает дублирование кода и упрощает обновления.
3️⃣Абстракция и инкапсуляция: функции позволяют абстрагироваться от деталей реализации, сосредоточив внимание на функциональности. Это улучшает понимание кода и уменьшает сложность. Кроме того, функции могут создавать границы, предотвращая воздействие изменений в одной части программы на другие.
4️⃣Тестирование: разбиение программы на функции упрощает процесс тестирования. Мы можем тестировать каждую функцию независимо, что делает обнаружение и устранение ошибок более эффективными.
5️⃣Разделение задач: функции позволяют разделять сложные задачи на меньшие подзадачи. Это делает разработку более систематической, позволяя решать проблемы последовательно и шаг за шагом.
👍11🥱7🤔2