Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Это практика автоматизации разработки, тестирования и развертывания программного обеспечения. Цель CI/CD — повысить скорость, частоту и надежность релизов, снижая риски и улучшая качество кода. Давайте разберем, что означает каждый компонент CI/CD и как они работают вместе.
Процесс регулярного объединения изменений кода из разных источников в общую кодовую базу. Обнаружение и устранение проблем на ранних стадиях разработки. Разработчики часто интегрируют свой код в общий репозиторий (например, несколько раз в день). Каждый коммит запускает автоматическую сборку и тестирование, чтобы убедиться, что изменения не сломали существующий код.
Инструменты: Jenkins, GitLab CI, Travis CI, CircleCI.
Практика, при которой код всегда готов к развертыванию в продакшен, но развертывание может требовать ручного вмешательства. Обеспечение готовности кода к релизу в любой момент времени. После успешного прохождения всех этапов CI, код автоматически продвигается к этапам развертывания на различные среды (staging, production). Требует минимального ручного вмешательства для выпуска новой версии.
Инструменты: Spinnaker, Bamboo, Jenkins.
Расширение Continuous Delivery, где каждое изменение, прошедшее все этапы тестирования, автоматически развертывается в продакшен. Полная автоматизация развертывания, минимизация времени между коммитом и доставкой кода пользователям. После успешного прохождения всех этапов CI и CD, изменения автоматически развертываются в продакшен без ручного вмешательства.
Инструменты: Jenkins, GitLab CI/CD, CircleCI, AWS CodePipeline.
Установите и настройте Jenkins на сервере.
Создайте новый pipeline проект в Jenkins.
В корне вашего репозитория создайте файл
Jenkinsfile
, который описывает этапы вашего CI/CD процесса.pipeline {
agent any
stages {
stage('Build') {
steps {
sh 'go build -v'
}
}
stage('Test') {
steps {
sh 'go test -v ./...'
}
}
stage('Deploy') {
steps {
sh 'echo "Deploying to production"'
// Ваши команды для развертывания
}
}
}
}
Коммиты в репозиторий автоматически запускают Pipeline, выполняющий сборку, тестирование и развертывание.
Автоматическое тестирование каждого изменения кода помогает быстро обнаруживать и устранять ошибки.
Регулярное объединение кода и тестирование улучшают качество и стабильность кода.
Автоматизация развертывания минимизирует человеческие ошибки и ускоряет выпуск новых версий.
Быстрая интеграция изменений позволяет разработчикам получать обратную связь о качестве кода в реальном времени.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Это инструменты для статического анализа кода, которые проверяют исходный код на соответствие заданным правилам и стандартам. Линтеры помогают находить потенциальные ошибки, улучшать стиль кода и обеспечивать его соответствие лучшим практикам.
Линтеры проверяют, соответствует ли код стилевым рекомендациям и стандартам, таким как использование отступов, именование переменных и форматирование.
Линтеры могут обнаруживать потенциальные ошибки, такие как неиспользуемые переменные, неправильные типы данных, неинициализированные переменные и другие проблемы.
Линтеры помогают поддерживать код в соответствии с общепринятыми стандартами и лучшими практиками, что улучшает читаемость и поддержку кода.
Линтеры могут указывать на участки кода, которые можно улучшить, например, упростить сложные конструкции или оптимизировать производительность.
golint
: Проверяет стиль кода на соответствие рекомендациям Go.gofmt
: Автоматически форматирует код в соответствии со стандартами Go.staticcheck
: Более мощный инструмент, который находит ошибки, неэффективные конструкции и другие проблемы.ESLint
: Очень мощный и настраиваемый линтер для JavaScript и TypeScriptJSHint
: Инструмент для выявления ошибок и потенциальных проблем в JavaScript-коде.Pylint
: Линтер для Python, который проверяет стиль кода, ищет ошибки и предлагает улучшения.flake8
: Комбинированный инструмент, который включает в себя проверки на стиль, ошибки и другие проблемы.Checkstyle
: Инструмент для проверки стиля кода Java.PMD
: Находит потенциальные ошибки, неиспользуемый код и другие проблемы в коде Java.golint
go install golang.org/x/lint/golint@latest
example.go
package main
import "fmt"
func main() {
fmt.Println("Hello, world!")
}
golint
golint example.go
ESLint
npm install eslint --save-dev
ESLint
npx eslint --init
example.js
function hello() {
console.log("Hello, world!");
}
hello();
Запустите
ESLint
:npx eslint example.js
Линтеры помогают всем разработчикам в команде придерживаться одного стиля кода, что улучшает читаемость и поддержку.
Линтеры могут обнаруживать ошибки еще до запуска кода, что сокращает время на отладку и тестирование.
Линтеры указывают на потенциальные проблемы и предлагают улучшения, что способствует написанию более качественного и надежного кода.
Использование линтеров помогает разработчикам учиться и развиваться, узнавая о лучших практиках и стандартах кода.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Линтеры (linters) нужны для обеспечения качества и чистоты кода, повышения его читаемости и поддержки, а также для предотвращения ошибок на ранних этапах разработки.
Линтеры анализируют код и обнаруживают синтаксические ошибки, неинициализированные переменные, неправильные типы данных и другие потенциальные проблемы еще до запуска программы.
Линтеры помогают разработчикам придерживаться единого стиля кода, что улучшает читаемость и поддержку проекта. Это особенно важно в больших командах, где много людей работают над одним проектом.
Линтеры указывают на потенциальные проблемы и предлагают улучшения, что способствует написанию более качественного и надежного кода. Например, линтеры могут рекомендовать избегать сложных конструкций или использовать более эффективные методы.
Линтеры автоматизируют проверку стиля и качества кода, освобождая разработчиков от рутинной работы и позволяя им сосредоточиться на более сложных задачах.
Линтеры помогают разработчикам узнавать о лучших практиках и стандартах кода, что способствует их профессиональному росту и развитию.
Линтеры упрощают поддержку кода, делая его более понятным и структурированным. Это особенно важно в долгосрочных проектах, где код может часто меняться.
golint
go install golang.org/x/lint/golint@latest
example.go
package main
import "fmt"
func main() {
fmt.Println("Hello, world!")
}
golint
golint example.go
ESLint
npm install eslint --save-dev
ESLint
npx eslint --init
example.js
function hello() {
console.log("Hello, world!");
}
hello();
ESLint
npx eslint example.js
Линтеры помогают поддерживать единообразие кода, что упрощает работу с ним и его сопровождение.
Раннее обнаружение ошибок позволяет сократить время на отладку и тестирование, улучшая производительность команды.
Линтеры обнаруживают потенциальные ошибки до запуска кода, что снижает вероятность появления багов в продакшене.
Автоматизация проверки стиля и качества кода позволяет разработчикам сосредоточиться на более важных задачах, повышая общую производительность команды.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Ключи в map (карте) должны обладать определенными свойствами, чтобы быть допустимыми и корректно работать с хеш-таблицей. Важно понимать, что ключи должны поддерживать операцию сравнения и быть хешируемыми.
Ключи должны поддерживать операцию сравнения с использованием оператора
==
. Это необходимо для проверки равенства ключей при выполнении операций вставки, поиска и удаления в карте.Ключи должны быть хешируемыми. Это значит, что для ключей должна существовать функция, которая преобразует их в хеш-код. Хеш-код используется для определения позиции ключа в хеш-таблице.
Булевый тип (bool)
m := map[bool]string{
true: "Yes",
false: "No",
}
Целочисленные типы (int, int8, int16, int32, int64, а также их беззнаковые эквиваленты uint, uint8, uint16, uint32, uint64)
m := map[int]string{
1: "One",
2: "Two",
}
Числа с плавающей точкой (float32, float64)
m := map[float64]string{
1.1: "One point one",
2.2: "Two point two",
}
Строки (string)
m := map[string]int{
"Alice": 25,
"Bob": 30,
}
Составные типы (структуры, массивы), при условии, что все их поля также поддерживают сравнение с помощью оператора ==
type Key struct {
FirstName string
LastName string
}
m := map[Key]int{
{"Alice", "Smith"}: 1,
{"Bob", "Johnson"}: 2,
}
slice
)Срезы не поддерживают операцию сравнения с использованием оператора
==
(только сравнение с nil
).map
)Карты не поддерживают операцию сравнения.
func
)Функции не поддерживают операцию сравнения.
package main
import "fmt"
type Person struct {
FirstName string
LastName string
}
func main() {
// Создаем карту с ключами типа Person
m := make(map[Person]int)
// Вставляем значения в карту
m[Person{"Alice", "Smith"}] = 25
m[Person{"Bob", "Johnson"}] = 30
// Выводим значения из карты
fmt.Println(m[Person{"Alice", "Smith"}]) // Выводит: 25
fmt.Println(m[Person{"Bob", "Johnson"}]) // Выводит: 30
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Оператор "квадратные скобки" (
[]
) при применении к строке используется для доступа к отдельным байтам в этой строке. Строки представлены как последовательности байтов, и оператор []
позволяет получить байт по указанному индексу. package main
import (
"fmt"
)
func main() {
str := "hello"
// Получаем байт по индексу
firstByte := str[0]
// Выводим байт и его символ
fmt.Printf("Первый байт: %d\n", firstByte) // Выводит: 104
fmt.Printf("Первый символ: %c\n", firstByte) // Выводит: h
}
В этой строке кода мы получаем байт, расположенный по индексу
0
в строке str
. В данном случае это байт, соответствующий символу 'h'.firstByte := str[0]
Здесь мы выводим байт в виде целого числа. Поскольку символ 'h' имеет ASCII-код 104, вывод будет
104
.fmt.Printf("Первый байт: %d\n", firstByte)
Мы также можем вывести байт как символ, используя формат
%c
. Это отобразит символ 'h'.fmt.Printf("Первый символ: %c\n", firstByte)
Важно понимать, что строки являются последовательностями байтов, а не символов. Это означает, что доступ по индексу с помощью
[]
дает байт, а не руну (rune). Если строка содержит многобайтовые символы (например, символы Unicode), то доступ по индексу может вернуть только один из байтов, составляющих символ.package main
import (
"fmt"
)
func main() {
str := "Привет"
// Получаем байт по индексу
firstByte := str[0]
// Выводим байт и его символ
fmt.Printf("Первый байт: %d\n", firstByte) // Выводит: 208
fmt.Printf("Первый символ: %c\n", firstByte) // Выводит: � (неполный символ)
}
Для корректной работы с многобайтовыми символами (рунами) в строках используется преобразование строки в срез рун
package main
import (
"fmt"
)
func main() {
str := "Привет"
// Преобразуем строку в срез рун
runes := []rune(str)
// Получаем руну по индексу
firstRune := runes[0]
// Выводим руну и её символ
fmt.Printf("Первая руна: %d\n", firstRune) // Выводит: 1055 (код Unicode для 'П')
fmt.Printf("Первый символ: %c\n", firstRune) // Выводит: П
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Слайсы являются ссылочными типами, поэтому простое присваивание одного слайса другому создаст новую ссылку на тот же подлежащий массив. Если вы хотите создать копию слайса с независимым подлежащим массивом, можно использовать встроенную функцию
copy
или методы, такие как использование append
.Создает побайтовую копию элементов из одного слайса в другой.
package main
import "fmt"
func main() {
original := []int{1, 2, 3, 4, 5}
// Создаем новый слайс той же длины, что и оригинал
copySlice := make([]int, len(original))
// Копируем элементы из оригинального слайса в новый
copy(copySlice, original)
// Изменяем элемент в копии
copySlice[0] = 100
fmt.Println("Оригинал:", original) // Выводит: Оригинал: [1 2 3 4 5]
fmt.Println("Копия:", copySlice) // Выводит: Копия: [100 2 3 4 5]
}
Использование функции
inal)
Чтобы создать новый слайс с копированными элементами.
package main
import "fmt"
func main() {
original := []int{1, 2, 3, 4, 5}
// Копируем элементы из оригинального слайса в новый слайс
copySlice := append([]int(nil), original...)
// Изменяем элемент в копии
copySlice[0] = 100
fmt.Println("Оригинал:", original) // Выводит: Оригинал: [1 2 3 4 5]
fmt.Println("Копия:", copySlice) // Выводит: Копия: [100 2 3 4 5]
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
1. В большинстве языков, ключи должны быть сравниваемыми типами (например, числа, строки, указатели).
2. Использование нестабильных или изменяемых ключей может привести к некорректной работе Map.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Позволяют создать и инициализировать слайс одновременно
package main
import "fmt"
func main() {
slice := []int{1, 2, 3, 4, 5}
fmt.Println(slice) // [1 2 3 4 5]
}
Позволяет создать слайс определенной длины и емкости
package main
import "fmt"
func main() {
slice := make([]int, 3) // Создаем слайс длиной 3 и емкостью 3
fmt.Println(slice) // [0 0 0]
sliceWithCapacity := make([]int, 3, 5) // Создаем слайс длиной 3 и емкостью 5
fmt.Println(sliceWithCapacity) // [0 0 0]
}
Указав подмножество элементов массива
package main
import "fmt"
func main() {
arr := [5]int{1, 2, 3, 4, 5}
slice := arr[1:4] // Слайс содержит элементы с индексами 1, 2 и 3
fmt.Println(slice) // [2 3 4]
}
Указав подмножество элементов существующего слайса
package main
import "fmt"
func main() {
slice := []int{1, 2, 3, 4, 5}
subSlice := slice[1:4] // Новый слайс содержит элементы с индексами 1, 2 и 3
fmt.Println(subSlice) // [2 3 4]
}
Длина и емкость которого равны нулю
package main
import "fmt"
func main() {
var emptySlice []int // Пустой слайс
fmt.Println(emptySlice, len(emptySlice), cap(emptySlice)) // [] 0 0
emptySlice = append(emptySlice, 1) // Добавление элемента
fmt.Println(emptySlice) // [1]
}
Указывая начальный и конечный индекс (исключительно)
package main
import "fmt"
func main() {
original := []int{1, 2, 3, 4, 5}
newSlice := original[:3] // Слайс содержит элементы с индексами 0, 1, 2
fmt.Println(newSlice) // [1 2 3]
anotherSlice := original[2:] // Слайс содержит элементы с индекса 2 до конца
fmt.Println(anotherSlice) // [3 4 5]
}
Использование всех методов
package main
import "fmt"
func main() {
// Создание слайса с использованием литерала
sliceLiteral := []int{1, 2, 3, 4, 5}
fmt.Println("Slice literal:", sliceLiteral)
// Создание слайса с использованием make
sliceMake := make([]int, 3) // Длина 3, емкость 3
fmt.Println("Slice make:", sliceMake)
sliceMakeWithCapacity := make([]int, 3, 5) // Длина 3, емкость 5
fmt.Println("Slice make with capacity:", sliceMakeWithCapacity)
// Создание слайса на основе массива
arr := [5]int{1, 2, 3, 4, 5}
sliceFromArray := arr[1:4] // Элементы с индексами 1, 2, 3
fmt.Println("Slice from array:", sliceFromArray)
// Создание слайса на основе другого слайса
sliceFromSlice := sliceLiteral[2:5] // Элементы с индексами 2, 3, 4
fmt.Println("Slice from slice:", sliceFromSlice)
// Создание пустого слайса
var emptySlice []int
fmt.Println("Empty slice:", emptySlice, len(emptySlice), cap(emptySlice))
// Добавление элемента в пустой слайс
emptySlice = append(emptySlice, 10)
fmt.Println("After append:", emptySlice)
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
1. Попытка записи в неинициализированный Map вызовет ошибку времени выполнения (panic).
2. Инициализация обязательна для корректной работы с Map.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Массивы и слайсы могут использоваться для хранения последовательности элементов одного типа. Когда вы "подставляете" переменную в массив или слайс, вы просто присваиваете значение этой переменной одному из элементов массива или слайса.
Пример с массивом
package main
import "fmt"
func main() {
// Создаем массив из 5 целых чисел
var arr [5]int
// Создаем переменную и присваиваем ей значение
x := 10
// Подставляем переменную в массив
arr[0] = x
// Выводим массив
fmt.Println(arr) // Выводит: [10 0 0 0 0]
}
Это создает массив
arr
из 5 целых чисел, все элементы которого инициализируются значением 0
.var arr [5]int
Создаем переменную
x
и присваиваем ей значение 10
.x := 10
Присваиваем значение переменной
x
первому элементу массива arr
.arr[0] = x
Выводит содержимое массива, показывая, что первый элемент массива теперь равен
10
, а остальные элементы остаются нулями.fmt.Println(arr)
Пример со слайсом
package main
import "fmt"
func main() {
// Создаем слайс из 3 целых чисел
slice := make([]int, 3)
// Создаем переменную и присваиваем ей значение
x := 20
// Подставляем переменную в слайс
slice[1] = x
// Выводим слайс
fmt.Println(slice) // Выводит: [0 20 0]
}
Это создает слайс
slice
из 3 целых чисел, все элементы которого инициализируются значением 0
.slice := make([]int, 3)
Создаем переменную
x
и присваиваем ей значение 20
.x := 20
Присваиваем значение переменной
x
второму элементу слайса slice
.slice[1] = x
Выводит содержимое слайса, показывая, что второй элемент слайса теперь равен
20
, а остальные элементы остаются нулями.fmt.Println(slice)
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
2. Добавление элементов: используйте функцию append для увеличения слайса.
3. Копирование: создавайте новый слайс и копируйте данные с помощью функции copy.
4. Избегание изменения оригинала: будьте осторожны с передачей слайсов, так как они передаются по ссылке.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Концепция "нулевого значения" (zero-value) означает значение по умолчанию, которое получает переменная при ее объявлении, если она не была инициализирована явно. Нулевые значения зависят от типа данных переменной.
0
0.0
false
""
nil
Является
nil
. Это означает, что слайс, объявленный, но не инициализированный явно, указывает на nil
и имеет длину и емкость равные нулю.Нулевое значение для слайса
package main
import "fmt"
func main() {
var slice []int // Объявление слайса без инициализации
fmt.Println(slice) // []
fmt.Println(len(slice)) // 0
fmt.Println(cap(slice)) // 0
fmt.Println(slice == nil) // true
}
Можно работать так же, как и с обычным слайсом. Например, можно добавлять элементы с помощью функции
append
, и это будет работать корректно.Использование
append
с nil
-слайсомpackage main
import "fmt"
func main() {
var slice []int // nil-слайс
// Добавление элемента в nil-слайс
slice = append(slice, 1)
fmt.Println(slice) // [1]
fmt.Println(len(slice)) // 1
fmt.Println(cap(slice)) // 1
fmt.Println(slice == nil) // false (теперь слайс больше не nil)
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
1. Хранение данных зависит от хеширования ключей, что делает порядок непредсказуемым.
2. Если нужен упорядоченный Map, используйте структуру, где порядок задаётся вручную, например, с помощью slice.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Слайсы представляют собой мощный и гибкий инструмент для работы с последовательностями элементов. Основаны на массивах, но они предоставляют более удобный и динамичный способ работы с данными.
Указатель на первый элемент массива, на который ссылается слайс.
Количество элементов, доступных в слайсе.
Максимальное количество элементов, которое может содержать слайс без перераспределения памяти.
Можно представить в виде структуры
type slice struct {
ptr *ElementType // Указатель на базовый массив
len int // Длина
cap int // Емкость
}
Можно создать из массива, указав диапазон элементов:
package main
import "fmt"
func main() {
arr := [5]int{1, 2, 3, 4, 5}
slice := arr[1:4] // Слайс содержит элементы с индексами 1, 2, 3
fmt.Println(slice) // [2 3 4]
}
Позволяет создать слайс определенной длины и емкости:
package main
import "fmt"
func main() {
slice := make([]int, 3, 5) // Слайс длиной 3 и емкостью 5
fmt.Println(slice) // [0 0 0]
}
Осуществляется так же, как и к элементам массива:
package main
import "fmt"
func main() {
slice := []int{1, 2, 3, 4, 5}
fmt.Println(slice[0]) // 1
slice[1] = 10
fmt.Println(slice) // [1 10 3 4 5]
}
Для этого используется функция
append
package main
import "fmt"
func main() {
slice := []int{1, 2, 3}
slice = append(slice, 4, 5) // Добавляем элементы 4 и 5 в конец слайса
fmt.Println(slice) // [1 2 3 4 5]
}
Можно создавать новые слайсы на основе существующих
package main
import "fmt"
func main() {
slice := []int{1, 2, 3, 4, 5}
subSlice := slice[1:4] // Слайс содержит элементы с индексами 1, 2, 3
fmt.Println(subSlice) // [2 3 4]
}
Для этого используется функция
copy
package main
import "fmt"
func main() {
src := []int{1, 2, 3}
dst := make([]int, len(src))
copy(dst, src)
fmt.Println(dst) // [1 2 3]
}
Могут автоматически изменять свою емкость при добавлении новых элементов с помощью
append
. Когда емкость текущего массива недостаточна для добавления новых элементов, создается новый массив с большей емкостью, в который копируются существующие элементы.package main
import "fmt"
func main() {
slice := make([]int, 3, 5)
fmt.Println("Before append:", slice, "Len:", len(slice), "Cap:", cap(slice))
slice = append(slice, 1, 2, 3)
fmt.Println("After append:", slice, "Len:", len(slice), "Cap:", cap(slice))
slice = append(slice, 4)
fmt.Println("After another append:", slice, "Len:", len(slice), "Cap:", cap(slice))
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
2. Литералы: для статических данных можно использовать литералы, например, map[string]int{"key": 1}.
3. Всегда проверяйте существование элемента с помощью value, ok := map[key], чтобы избежать ошибок доступа к несуществующим ключам.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM