Это практика автоматизации разработки, тестирования и развертывания программного обеспечения. Цель 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
👍5❤2
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔2🤯1
Это инструменты для статического анализа кода, которые проверяют исходный код на соответствие заданным правилам и стандартам. Линтеры помогают находить потенциальные ошибки, улучшать стиль кода и обеспечивать его соответствие лучшим практикам.
Линтеры проверяют, соответствует ли код стилевым рекомендациям и стандартам, таким как использование отступов, именование переменных и форматирование.
Линтеры могут обнаруживать потенциальные ошибки, такие как неиспользуемые переменные, неправильные типы данных, неинициализированные переменные и другие проблемы.
Линтеры помогают поддерживать код в соответствии с общепринятыми стандартами и лучшими практиками, что улучшает читаемость и поддержку кода.
Линтеры могут указывать на участки кода, которые можно улучшить, например, упростить сложные конструкции или оптимизировать производительность.
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
❤1👍1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔5😁2
Линтеры (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
👍1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5❤1👍1
Ключи в 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
👍7❤1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3❤2
Оператор "квадратные скобки" (
[]
) при применении к строке используется для доступа к отдельным байтам в этой строке. Строки представлены как последовательности байтов, и оператор []
позволяет получить байт по указанному индексу. 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
❤3👍3
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3❤1
Слайсы являются ссылочными типами, поэтому простое присваивание одного слайса другому создаст новую ссылку на тот же подлежащий массив. Если вы хотите создать копию слайса с независимым подлежащим массивом, можно использовать встроенную функцию
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
👍6🔥1
1. В большинстве языков, ключи должны быть сравниваемыми типами (например, числа, строки, указатели).
2. Использование нестабильных или изменяемых ключей может привести к некорректной работе Map.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Позволяют создать и инициализировать слайс одновременно
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
👍5
1. Попытка записи в неинициализированный Map вызовет ошибку времени выполнения (panic).
2. Инициализация обязательна для корректной работы с Map.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3❤2
Массивы и слайсы могут использоваться для хранения последовательности элементов одного типа. Когда вы "подставляете" переменную в массив или слайс, вы просто присваиваете значение этой переменной одному из элементов массива или слайса.
Пример с массивом
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❤1🤯1
2. Добавление элементов: используйте функцию append для увеличения слайса.
3. Копирование: создавайте новый слайс и копируйте данные с помощью функции copy.
4. Избегание изменения оригинала: будьте осторожны с передачей слайсов, так как они передаются по ссылке.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Концепция "нулевого значения" (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
👍2❤1
1. Хранение данных зависит от хеширования ключей, что делает порядок непредсказуемым.
2. Если нужен упорядоченный Map, используйте структуру, где порядок задаётся вручную, например, с помощью slice.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
❤1👍1
Слайсы представляют собой мощный и гибкий инструмент для работы с последовательностями элементов. Основаны на массивах, но они предоставляют более удобный и динамичный способ работы с данными.
Указатель на первый элемент массива, на который ссылается слайс.
Количество элементов, доступных в слайсе.
Максимальное количество элементов, которое может содержать слайс без перераспределения памяти.
Можно представить в виде структуры
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
❤1👍1
2. Литералы: для статических данных можно использовать литералы, например, map[string]int{"key": 1}.
3. Всегда проверяйте существование элемента с помощью value, ok := map[key], чтобы избежать ошибок доступа к несуществующим ключам.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM