💬 Как получить из среза массив и для чего это может быть нужно?
1. С использованием
2. С использованием
Такое преобразование может потребоваться, когда мы хотим использовать срез как ключ в типе
Поскольку в Go ключи мапы должны быть comparable, мы можем использовать массив с фиксированным размером вместо среза.
1. С использованием
unsafe
:package main
import (
"fmt"
"unsafe"
)
func main() {
slice := []int{1, 2, 3}
arrayPtr := (*[3]int)(unsafe.Pointer(&slice[0]))
fmt.Println(*arrayPtr)
}
2. С использованием
copy
:package main
import "fmt"
func main() {
slice := []int{1, 2, 3}
var array [3]int
copy(array[:], slice)
fmt.Println(array)
}
Такое преобразование может потребоваться, когда мы хотим использовать срез как ключ в типе
map
. Поскольку в Go ключи мапы должны быть comparable, мы можем использовать массив с фиксированным размером вместо среза.
🤔9👍3
💬 Что такое inode в Linux?
🔸 Inode (Index Node) — это структура данных, используемая файловой системой для хранения информации о файле или директории, включая права доступа, информацию о владельце, группе, размере, временных метках создания и изменения, а также указатели на блоки данных на диске, где хранится само содержимое файла.
🔸 Директории — это тоже inode типа директория, в которых вместо содержимого файла содержится список имён файлов и номера их inode. Корневая директория в Ext4 имеет номер inode — 2.
🔸 Inode имеют ограниченный размер, поэтому количество файлов или каталогов, которые могут быть созданы в файловой системе, ограничено.
🔸 Inode (Index Node) — это структура данных, используемая файловой системой для хранения информации о файле или директории, включая права доступа, информацию о владельце, группе, размере, временных метках создания и изменения, а также указатели на блоки данных на диске, где хранится само содержимое файла.
🔸 Директории — это тоже inode типа директория, в которых вместо содержимого файла содержится список имён файлов и номера их inode. Корневая директория в Ext4 имеет номер inode — 2.
🔸 Inode имеют ограниченный размер, поэтому количество файлов или каталогов, которые могут быть созданы в файловой системе, ограничено.
❤6🥱5🔥3👍2
💬 Что такое шардирование и для чего оно предназначено?
Шардирование (или шардинг) — это разделение хранилища на несколько независимых частей, шардов. Шардирование — это не репликация, в случае которой выделенные экземпляры базы данных являются не составными частями общего хранилища, а копиями друг друга.
🔹 Виды шардинга: вертикальное и горизонтальное.
🔹 Методы шардинга: хешированное, диапазонное, круговое и динамическое.
🔹 Способы шардирования: средствами БД, надстройками к БД и клиентскими средствами.
Шардирование (или шардинг) — это разделение хранилища на несколько независимых частей, шардов. Шардирование — это не репликация, в случае которой выделенные экземпляры базы данных являются не составными частями общего хранилища, а копиями друг друга.
🔹 Виды шардинга: вертикальное и горизонтальное.
🔹 Методы шардинга: хешированное, диапазонное, круговое и динамическое.
🔹 Способы шардирования: средствами БД, надстройками к БД и клиентскими средствами.
👍5
💬 Как в Go обрабатываются операции ввода-вывода файлов?
В Go для работы с файлами и операциями ввода-вывода используется пакет
📌 Открытие и чтение файла
Для чтения файла сначала его нужно открыть с помощью функции
📌 Создание, запись в файл и добавление данных в файл
Для создания файла используется функция
В Go для работы с файлами и операциями ввода-вывода используется пакет
os
для открытия, создания, чтения, записи и закрытия файлов, а также пакет io
или bufio
для более эффективного ввода-вывода с буферизацией.📌 Открытие и чтение файла
Для чтения файла сначала его нужно открыть с помощью функции
os.Open()
, а затем можно использовать io
или bufio
для чтения содержимого:package main
import (
"bufio"
"fmt"
"log"
"os"
)
func main() {
file, err := os.Open("example.txt")
if err != nil {
log.Fatal(err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
fmt.Println(scanner.Text())
}
if err := scanner.Err(); err != nil {
log.Fatal(err)
}
}
📌 Создание, запись в файл и добавление данных в файл
Для создания файла используется функция
os.Create()
, а для записи — метод Write()
или WriteString()
из пакета os.
Чтобы дополнить файл, его нужно открыть с опциями os.O_APPEND
и os.O_WRONLY.
👍5❤2
💬 Что такое context switching в Go?
Это процесс, при котором Go-планировщик переключает выполнение с одной горутины на другую, позволяя множеству горутин эффективно выполняться конкурентно.
Планировщик Go использует модель M:N, где множество горутин (G) распределяются на меньшее количество потоков операционной системы (M), привязанных к логическим процессорам (P), и опирается на кооперативный планировщик для переключения контекста на основе явных событий, таких как синхронизация, системные вызовы и операции ввода-вывода.
Это обеспечивает эффективное использование ресурсов и способствует более высокой производительности и масштабируемости приложений на Go, минимизируя задержки и оверхед, связанные с переключением контекста.
👉 Подробнее
Это процесс, при котором Go-планировщик переключает выполнение с одной горутины на другую, позволяя множеству горутин эффективно выполняться конкурентно.
Планировщик Go использует модель M:N, где множество горутин (G) распределяются на меньшее количество потоков операционной системы (M), привязанных к логическим процессорам (P), и опирается на кооперативный планировщик для переключения контекста на основе явных событий, таких как синхронизация, системные вызовы и операции ввода-вывода.
Это обеспечивает эффективное использование ресурсов и способствует более высокой производительности и масштабируемости приложений на Go, минимизируя задержки и оверхед, связанные с переключением контекста.
👉 Подробнее
Ardan Labs
Scheduling In Go : Part II - Go Scheduler
Ardan Labs is trusted by small startups and Fortune 500 companies to train their engineers and develop business software solutions and applications.
👍7❤1
💬 Какие кейсы использования default в select?
Использование
📌 Это особенно полезно для:
☑️ Реализации таймаутов или опроса с немедленным возвратом, когда операции с каналами не готовы.
☑️ Создания циклов обработки событий, где
Использование
default
в select
в Go обеспечивает неблокирующую операцию. Если все другие каналы в select
блокированы, выполнение сразу переходит к default,
позволяя программе продолжить выполнение без ожидания. 📌 Это особенно полезно для:
☑️ Реализации таймаутов или опроса с немедленным возвратом, когда операции с каналами не готовы.
☑️ Создания циклов обработки событий, где
default
может обрабатывать фоновые задачи или проверки состояния, не прерывая основной поток выполнения.🔥8
💬 Что такое NaN и почему NaN не равно NaN?
NaN означает "Not a Number" (не число) и представляет собой специальное значение во многих системах с плавающей запятой, используемых в языках программирования, включая Go, для обозначения результата операций, которые не могут быть определены в терминах числового значения.
Примерами таких операций являются деление нуля на ноль, извлечение квадратного корня из отрицательного числа в контексте вещественных чисел, или любые другие операции, результат которых не может быть представлен в рамках обычной числовой системы.
Согласно стандарту IEEE 754, который определяет арифметику плавающей запятой, любая операция, возвращающая NaN, не должна быть равна никакому числу, включая само NaN. Это правило подчеркивает тот факт, что NaN обозначает неопределенность или результат, который не является числовым значением, и следовательно, сравнение на равенство (или неравенство) с другими числами или даже с самим NaN не имеет смысла, так как неопределенность не может быть равна (или не равна) чему-либо конкретному.
NaN означает "Not a Number" (не число) и представляет собой специальное значение во многих системах с плавающей запятой, используемых в языках программирования, включая Go, для обозначения результата операций, которые не могут быть определены в терминах числового значения.
Примерами таких операций являются деление нуля на ноль, извлечение квадратного корня из отрицательного числа в контексте вещественных чисел, или любые другие операции, результат которых не может быть представлен в рамках обычной числовой системы.
Согласно стандарту IEEE 754, который определяет арифметику плавающей запятой, любая операция, возвращающая NaN, не должна быть равна никакому числу, включая само NaN. Это правило подчеркивает тот факт, что NaN обозначает неопределенность или результат, который не является числовым значением, и следовательно, сравнение на равенство (или неравенство) с другими числами или даже с самим NaN не имеет смысла, так как неопределенность не может быть равна (или не равна) чему-либо конкретному.
👍17❤2
💬 Если в функции Go есть return, обязательно ли она вернет то, что указано в операторе?
🔸 Если в функции указан
🔸 В Go можно использовать именованные возвращаемые значения в сигнатуре функции. В таком случае, функция может использовать
🔸 Если функция не имеет возвращаемых значений (то есть, её сигнатура не включает возвращаемые типы), использование
🔸 Если в функции указан
return
, то она должна вернуть значение(-я), соответствующие её сигнатуре.🔸 В Go можно использовать именованные возвращаемые значения в сигнатуре функции. В таком случае, функция может использовать
return
без явного указания возвращаемого значения, в результате чего будут возвращены текущие значения именованных возвращаемых переменных. Это не меняет факта, что функция возвращает значения, но позволяет не указывать их явно в операторе return
.🔸 Если функция не имеет возвращаемых значений (то есть, её сигнатура не включает возвращаемые типы), использование
return
просто завершает выполнение функции. В таком случае, return
не возвращает никакого значения.👍6🤔6⚡1
🧑💻 Статьи для IT: как объяснять и распространять значимые идеи
Напоминаем, что у нас есть бесплатный курс для всех, кто хочет научиться интересно писать — о программировании и в целом.
Что: семь модулей, посвященных написанию, редактированию, иллюстрированию и распространению публикаций.
Для кого: для авторов, копирайтеров и просто программистов, которые хотят научиться интересно рассказывать о своих проектах.
👉Материалы регулярно дополняются, обновляются и корректируются. А еще мы отвечаем на все учебные вопросы в комментариях курса.
Напоминаем, что у нас есть бесплатный курс для всех, кто хочет научиться интересно писать — о программировании и в целом.
Что: семь модулей, посвященных написанию, редактированию, иллюстрированию и распространению публикаций.
Для кого: для авторов, копирайтеров и просто программистов, которые хотят научиться интересно рассказывать о своих проектах.
👉Материалы регулярно дополняются, обновляются и корректируются. А еще мы отвечаем на все учебные вопросы в комментариях курса.
💬 Для чего предназначены tickers в Go и как их реализовать?
Tickers в Go предназначены для выполнения повторяющихся действий через равные промежутки времени.
Tickers используют каналы Go для отправки сигнала по истечении каждого интервала времени.
Реализовать ticker на Go можно с использованием пакета
В примере создаётся
Tickers в Go предназначены для выполнения повторяющихся действий через равные промежутки времени.
Tickers используют каналы Go для отправки сигнала по истечении каждого интервала времени.
Реализовать ticker на Go можно с использованием пакета
time
. Простой пример использования:
package main
import (
"fmt"
"time"
)
func main() {
ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop()
for {
select {
case <-ticker.C:
fmt.Println("Tick at", time.Now())
// ...
}
}
}
В примере создаётся
ticker
, который «тикает» каждую секунду. В бесконечном цикле программа ожидает сигнала от ticker.C
, канала тикера. Каждый раз, когда тикер отправляет сигнал в свой канал (то есть каждую секунду), программа выполняет код внутри case <-ticker.C
, в данном случае печатая текущее время.👍25
-35% на полугодовой курс по алгоритмам!
🌟 Алгоритмы и структуры данных🌟
23 390 рублей35 990 рублей до 1 апреля
Курс для тех, кто хочет научиться работать с алгоритмами, подготовиться к собеседованию крупную IT-компанию и начать брать более сложные проекты.
🔥 Переходите и активируйте вводные занятия курса — https://proglib.io/w/5a72cc41
Вас ждут:
– 150 практических заданий и 47 видеолекций
– бессрочный доступ к обучению
– поддержка преподавателя в чате
А также очень харизматичный спикер из Яндекса 🙌🏻
🌟 Алгоритмы и структуры данных🌟
23 390 рублей
Курс для тех, кто хочет научиться работать с алгоритмами, подготовиться к собеседованию крупную IT-компанию и начать брать более сложные проекты.
🔥 Переходите и активируйте вводные занятия курса — https://proglib.io/w/5a72cc41
Вас ждут:
– 150 практических заданий и 47 видеолекций
– бессрочный доступ к обучению
– поддержка преподавателя в чате
А также очень харизматичный спикер из Яндекса 🙌🏻
Forwarded from Книги для Go разработчиков
This media is not supported in the widget
VIEW IN TELEGRAM
❤4
💬 Для чего в приведенном коде предназначена конструкция "_ struct{}"?
Конструкция
Это значит, что мы не сможем случайно инициализировать
В Go, когда мы инициализируем структуру без указания имён полей, например:
Это называется неименованным или позиционным литералом. Такой способ инициализации может привести к ошибкам, особенно если порядок полей в структуре изменится или будут добавлены новые поля.
Добавление поля
Конструкция
_ struct{}
используется для предотвращения создания литералов структур без именованных полей при инициализации ProgInfo
. Это значит, что мы не сможем случайно инициализировать
ProgInfo
без указания имён полей, что может помочь избежать ошибок и повысить читаемость кода, особенно когда структура со временем расширяется новыми полями.В Go, когда мы инициализируем структуру без указания имён полей, например:
info := ProgInfo{0, 1, 2, 3}
Это называется неименованным или позиционным литералом. Такой способ инициализации может привести к ошибкам, особенно если порядок полей в структуре изменится или будут добавлены новые поля.
Добавление поля
_ struct{}
делает такую инициализацию невозможной, требуя от разработчика использовать именованные литералы, где каждое значение присваивается конкретному имени поля:
info := ProgInfo{
Flags: 0,
Reguse: 1,
Regset: 2,
Regindex: 3,
}
👍75😁5❤2
⚡️Proglib запускает каналы про нейросети
По каждому направлению отдельно! А именно:
⭐Библиотека нейрозвука — здесь все, связанное с транскрибацией, синтезом речи, ИИ-музыкой
⭐Библиотека нейротекста — классические ИИ-помощники вроде ChatGPT, Gemini, Bing
⭐Библиотека нейровидео — здесь пишем про нашумевшую Sora AI, а также про Runway ML, дипфейки и другие видеотехнологии
⭐Библиотека нейрокартинок — генерируем изображения и рассказываем про Midjourney, DALL-E, Stable Diffusion
⭐️Библиотека робототехники и беспилотников — наконец, тут мы рассказываем не столько про ИИ, сколько про роботов, беспилотные технологии и интернет вещей
И все это — максимально подробно: с пошаговыми инструкциями, промтами, инструментами и лайфхаками.
Подписывайтесь!
По каждому направлению отдельно! А именно:
⭐Библиотека нейрозвука — здесь все, связанное с транскрибацией, синтезом речи, ИИ-музыкой
⭐Библиотека нейротекста — классические ИИ-помощники вроде ChatGPT, Gemini, Bing
⭐Библиотека нейровидео — здесь пишем про нашумевшую Sora AI, а также про Runway ML, дипфейки и другие видеотехнологии
⭐Библиотека нейрокартинок — генерируем изображения и рассказываем про Midjourney, DALL-E, Stable Diffusion
⭐️Библиотека робототехники и беспилотников — наконец, тут мы рассказываем не столько про ИИ, сколько про роботов, беспилотные технологии и интернет вещей
И все это — максимально подробно: с пошаговыми инструкциями, промтами, инструментами и лайфхаками.
Подписывайтесь!
💬 В чем разница между методами Time.Sub() и Time.Add() пакета time?
Ключевое отличие между методами
💬 Почему они оба не принимают
Причина в том, что
Методы
Как показано в примере,
Ключевое отличие между методами
Time.Add()
и Time.Sub()
в пакете time
заключается в их параметрах и возвращаемых значениях. Time.Add()
принимает параметр Duration
и возвращает значение Time, в то время как Time.Sub()
принимает параметр Time и возвращает Duration
.💬 Почему они оба не принимают
Duration
и не возвращают Time
?Причина в том, что
Time.Add()
может обрабатывать отрицательные аргументы, эффективно выполняя операцию вычитания. Следовательно, не имело бы смысла иметь другой метод Time.Sub()
, который также принимает Duration
.Методы
Time.Add()
и Time.Sub()
служат разным целям и имеют различные сигнатуры для обработки конкретных юзкейсов:package main
import (
"fmt"
"time"
)
func main() {
now := time.Now()
newTime := now.Add(2 * time.Hour)
fmt.Println("Time after 2 hours:", newTime)
newTime = now.Add(-2 * time.Hour)
fmt.Println("Time before 2 hours:", newTime)
duration := newTime.Sub(now)
fmt.Println("Duration newTime to now:", duration)
}
Как показано в примере,
Time.Add()
используется для добавления или вычитания продолжительности из временного значения, в то время как Time.Sub()
используется для вычисления продолжительности между двумя временными значениями.👍13❤3
💬 Как правильно отправить эти данные в теле HTTP POST запроса?
Для отправки данных в теле HTTP POST запроса важно знать тип содержимого. Поскольку это сырой текст, мы будем использовать тип содержимого
Интерфейс
Чтобы соответствовать требованиям, мы преобразуем тело в буфер, который реализует этот интерфейс:
data := "test data"
Для отправки данных в теле HTTP POST запроса важно знать тип содержимого. Поскольку это сырой текст, мы будем использовать тип содержимого
text/plain
. Функция http.Post
требует io.Reader
в качестве тела, а не строки или байтов:
Post(url string, contentType string, body io.Reader) (resp *http.Response, err error)
Интерфейс
Reader
определен следующим образом:
type Reader interface {
Read(p []byte) (n int, err error)
}
Чтобы соответствовать требованиям, мы преобразуем тело в буфер, который реализует этот интерфейс:
func main() {
data := "test data"
contentType := "text/plain"
body := strings.NewReader(data)
// или
// body := bytes.NewBufferString(data)
resp, err := http.Post("https://example.com", contentType, body)
// ....
}
👍18🤔2
💬 В чем заключается риск использования глобальных переменных, особенно изменяемых?
Глобальные переменные — это те, которые мы размещаем вне функций или методов, доступные для любой части нашего кода для использования и изменения. Часто они приносят больше проблем, чем пользы. Вот почему:
🔹 Отслеживание изменений затруднено: определить, где была изменена переменная
🔹 Тестирование усложняется: предположим, мы тестируем новый и старый процессы оформления заказа. Если оба теста вмешиваются в один и тот же глобальный featureConfig, мы не сможем тестировать их независимо, не мешая один другому.
🔹 Проблемы с конкурентностью: когда несколько запросов пытаются одновременно читать или изменять
📌 Что делать? Dependency injection👇
Это метод, при котором мы предоставляем объекту его потребности извне, вместо того чтобы создавать их самостоятельно или брать из глобальных переменных.
Да, этот метод делает вещи немного более сложными, но он также упрощает поддержку кода, его тестирование и поиск ошибок.
С внедрением зависимостей настройка тестов для сценариев с включенными и отключенными функциями становится простой.
Но если наши глобальные переменные не изменяются, не требуют тестирования и должны работать именно так, то в этих ситуациях использование глобальных переменных может быть более предпочтительным.
Также, если мы используем глобальные переменные, которые изменяются во время выполнения, необходимо убедиться, что мы используем техники синхронизации.
Глобальные переменные — это те, которые мы размещаем вне функций или методов, доступные для любой части нашего кода для использования и изменения. Часто они приносят больше проблем, чем пользы. Вот почему:
🔹 Отслеживание изменений затруднено: определить, где была изменена переменная
featureConfig.NewCheckoutProcessEnabled
в вашем приложении, сложно, когда любая часть кода может её изменить.🔹 Тестирование усложняется: предположим, мы тестируем новый и старый процессы оформления заказа. Если оба теста вмешиваются в один и тот же глобальный featureConfig, мы не сможем тестировать их независимо, не мешая один другому.
🔹 Проблемы с конкурентностью: когда несколько запросов пытаются одновременно читать или изменять
featureConfig
, это может привести к несоответствиям (состояние гонки).📌 Что делать? Dependency injection
Это метод, при котором мы предоставляем объекту его потребности извне, вместо того чтобы создавать их самостоятельно или брать из глобальных переменных.
Да, этот метод делает вещи немного более сложными, но он также упрощает поддержку кода, его тестирование и поиск ошибок.
С внедрением зависимостей настройка тестов для сценариев с включенными и отключенными функциями становится простой.
Но если наши глобальные переменные не изменяются, не требуют тестирования и должны работать именно так, то в этих ситуациях использование глобальных переменных может быть более предпочтительным.
Также, если мы используем глобальные переменные, которые изменяются во время выполнения, необходимо убедиться, что мы используем техники синхронизации.
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Forwarded from Библиотека Go-разработчика | Golang
context.Context
?HTTP-обработчики могут использовать контекст для управления тайм-аутами запросов или отменой в рамках запроса. Тип
Context
также позволяет передавать значения (например, идентификатор пользователя, связанный с запросом) другим функциям.❓Следует ли использовать этот механизм для передачи информации по цепочке вызовов запроса? Или лучше использовать обычную структуру?
Вот две причины, по которым использование
Context
для передачи значений может быть плохой идеей:Значения в
Context
представляют собой пары ключ/значение, где ключ и значение являются пустыми интерфейсами (т. е. any
). Другими словами, значения в контексте — это как мешок со всем подряд. Компилятор не может помочь вам отловить ошибки типов или даже проверить, есть ли информация. Удачи в устранении неполадок 😉Если вы видите функцию, принимающую параметр
Context
, вы не можете сказать, что внутри. Если вы видите функцию, которая принимает параметр структуры, вы можете ясно видеть, что данные передаются, и что это за данные.❓Но разве
doSomething(ctx)
не выглядит намного чище, чем doSomething(ctx, someStruct)
?Чистый код сам по себе не является целью. Код не чист только потому, что он короткий. Код чистый, если читатель может ясно видеть, что он делает.
❓Так
context.WithValue()
следует избегать?Значения в контексте могут быть полезны, если они не критичны для бизнес-логики приложения. Например, совершенно нормально передавать идентификаторы запросов для логирования или измерения метрик. Читатель все равно сможет понять логику кода, и если что-то пойдет не так с этим идентификатором, это повлияет только на логирование или метрики приложения, но не на результат запроса.
Context
.#tip
Please open Telegram to view this post
VIEW IN TELEGRAM
👍15❤1
💬 Что необходимо, чтобы две функции считались одного типа?
Чтобы две функции считались одного типа в Go, они должны иметь одинаковую сигнатуру функции.
Это означает, что они должны иметь совпадающие параметры (количество, типы) и возвращаемые значения.
Чтобы две функции считались одного типа в Go, они должны иметь одинаковую сигнатуру функции.
Это означает, что они должны иметь совпадающие параметры (количество, типы) и возвращаемые значения.
type sigFunc func(a int, b float64) (bool, error)
func functionA(a int, b float64) (bool, error) {
return true, nil
}
func functionB(a int, b float64) (bool, error) {
return false, nil
}
func main() {
var x sigFunc = functionA
x = functionB
print(x)
}
❤17