Держите годный контент
О чём вообще речь в этом видео?
В целом, обсуждается масса полезных вещей, так что видео стоит глянуть
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Держите отличную статью, где разработчики из YADRO описывают best-practices в Go-разработке
О чём статья?
А также, конечно, освещается тема правильной архитектуры, включая разделение кода на пользовательские кейсы, глаголы и существительные и много всего ещё — должно быть полезно
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
package main
import (
"context"
"fmt"
"log"
"time"
"github.com/jackc/pgx"
)
type DatabaseInstance struct {
conn *pgx.Conn
connConfig pgx.ConnConfig
maxConnectAttempts int
}
func NewConn(uri string, maxAttempts int) (*DatabaseInstance, error) {
connConfig, err := pgx.ParseURI(uri)
if err != nil {
return nil, err
}
instance := DatabaseInstance{}
instance.connConfig = connConfig
instance.maxConnectAttempts = maxAttempts
return &instance, err
}
func (db *DatabaseInstance) reconnect() (*pgx.Conn, error) {
conn, err := pgx.Connect(db.connConfig)
if err != nil {
return nil, fmt.Errorf("unable to connection to database: %v", err)
}
if err = conn.Ping(context.Background()); err != nil {
return nil, fmt.Errorf("couldn't ping postgre database: %v", err)
}
return conn, err
}
func (db *DatabaseInstance) GetConn() *pgx.Conn {
var err error
if db.conn == nil {
if db.conn, err = db.reconnect(); err != nil {
log.Fatalf("%s", err)
}
}
if err = db.conn.Ping(context.Background()); err != nil {
attempt := 0
ticker := time.NewTicker(5 * time.Second)
defer ticker.Stop()
for range ticker.C {
if attempt >= db.maxConnectAttempts {
log.Fatalf("connection failed after %d attempt\n", attempt)
}
attempt++
log.Println("reconnecting...")
db.conn, err = db.reconnect()
if err == nil {
return db.conn
}
log.Printf("connection was lost. Error: %s. Waiting for 5 sec...\n", err)
}
}
return db.conn
}
Код довольно прост: мы перед взятием соединения пингуем БД, если этого не удалось сделать, то ждём 5 секунд и пытаемся снова.
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
Встречайте годный контент!
В этой статье детально и подробно описана работа планировщика Go, разобраны основные моменты, связанные с горутинами
Вот некоторые факты из статьи:
M
горутин к N
потокам ядра, формируя модель M:N
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
Для тех, у кого руки ещё не дошли до свежей февральской версии Go — держите годное видео от разраба из Авито, рассказывает про некоторые нововведения и всё такое
В частности про:
split
из пакета strings
, позволяющую разделить строку на частиrand
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Держите полезный ролик, в котором на разные вопросы, связанные с тестированием Go-кода, отвечает разработчик с опытом 8 лет.
О чём говорится в видео?
— Краткое введение в тестирование: что такое тесты и какие виды тестов существуют.
— Должен ли разработчик писать тесты?
— Что такое TDD?
— «Утром код — вечером тесты» или «Утром тесты — вечером код»?
— Какую логику и какие данные нужно тестировать, а когда тесты не нужны.
— Как TDD помогает увеличить скорость и снизить затраты на разработку.
— Забиваете на best practices во время инцидентов? Остановитесь и подумайте.
— Как хорошие тесты становятся документацией к коду.
— Что такое test cases и как они связаны с use cases.
— Как методика TDD влияет на структуру команды и процессы.
— Что такое технический долг.
— Как «постмортем» помогает не воспроизводить одни и те же фейлы.
— Что ещё почитать по про test driven development.
В целом, полезное видео, рекомендую
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
Интерфейсы в Go — это способ реализации полиморфизма
package main
import (
"math"
"fmt"
)
// Круг.
type Circle struct {
x, y, r float64
}
// Прямоугольник.
type Rectangle struct {
x1, y1, x2, y2 float64
}
// Интерфейс фигуры, которому удовлетворяют все типы, имеющие соответствующий
// метод вычисления площади Area().
type Figure interface {
Area() float64
}
// Реализация интерфейса Figure для Circle.
func (c *Circle) Area() float64 {
return math.Pi * c.r * c.r
}
// Реализация интерфейса Figure для Rectangular.
func (r *Rectangle) Area() float64 {
return math.Abs(r.x2 - r.x1) * math.Abs(r.y2 - r.y1)
}
func main() {
figures := make([]Figure, 0) // Срез фигур.
// Мы можем добавлять в этот срез все, что удовлетворяет интерфейсу
// Figure, несмотря на то, что это элементы разных типов:
figures = append(figures, &Circle{0, 0, 10})
figures = append(figures, &Rectangle{0, 0, 10, 20})
// И теперь мы можем единообразно обрабатывать эти данные разных типов.
for _, figure := range figures {
fmt.Printf("Area of %#v = %f\n", figure, figure.Area())
}
}
$ go run figures.go
Area of &main.Circle{x:0, y:0, r:10} = 314.159265
Area of &main.Rectangle{x1:0, y1:0, x2:10, y2:20} = 200.000000
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
v1 := Struct{}
v2 := &Struct{}
В чём отличие? Понятно, что во втором случае передается указатель, но когда что нужно использовать?
Struct
и присваивает его переменной v1
. В этом случае переменная v1
будет содержать саму структуру, а не указатель на нее.Struct
с помощью оператора &
, который возвращает указатель на структуру, и присваивает этот указатель переменной v2
. В этом случае переменная v2
будет содержать указатель на структуру, а не саму структуру.type Struct struct {
Value int
}
func main() {
v1 := Struct{} // Создаем структуру
v1.Value = 10 // Изменяем поле Value
v2 := &Struct{} // Создаем указатель на структуру
v2.Value = 20 // Изменяем поле Value через указатель
fmt.Println(v1.Value) // Выводит 10
fmt.Println(v2.Value) // Выводит 20
}
Struct
и изменяем поле Value
сначала через саму структуру, а затем через указатель на структуру. Оба вывода будут отличаться, потому что изменения сделанные через указатель на структуру будут отражаться на самой структуре, в то время как изменения, сделанные через саму структуру, не влияют на указатель на нее.@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
"Second"
и "Third"
(хотя они должны идти после "First"
), а "Fourth"
как раз лишь только после "First"
? Ведь
defer
должен срабатывать перед закрытием функции, в которой он объявлен.package main
import "fmt"
func main() {
defer fmt.Println(changePointer())
fmt.Println("First")
}
func changePointer() string {
defer fmt.Println("Third")
fmt.Println("Second")
return "Fourth"
}
changePointer()
вызывается, потому что это необходимо для получения результата, который может быть использован в fmt.Println(changePointer())
. Функция
changePointer
выполняется, чтобы получить результат, который возвращается в main
, и только после этого запланированные defer
— вызовы выполняются.Вот такие дела
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
fmt.Scanln()
, тут все понятно. Далее необходимо вывести
True
, если строка состоит из цифр и False
во всех остальных случаях. Как это можно сделать?^\d*$
или, что аналогично: ^[0-9]*$
.test:="1233455677789900066554436433"
pattern:=`^\d*$`
matched,err:= regexp.Match(pattern,
[]byte(test))
Ну и неплохо бы ещё прикрутить обработку ошибок
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
Согласно Statista, больше 80% организаций со штатом от 5000 сотрудников используют микросервисную архитектуру, или микросервисы. Разработка микросервисов помогает бизнесу масштабироваться, делают приложения надежнее и упрощают кодовую базу. Но подходят они не всем.
Держите полезную статью о том, что такое микросервисы, в чем их преимущества и когда для бизнеса есть смысл на них переходить.
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Вот первая идея, которая приходит в голову; тут используются регулярные выражения:
import (
"regexp"
)
func main() {
str := "Некая строка c кириллическими символами"
re := regexp.MustCompile("[А-Яа-я]+?") //проверяем на киррилические символы
isRussian := re.MatchString(str)
if isRussian {
...
}
}
Есть ли более эффективный способ узнать, на каком языке написана строка? Языков только два - русский и английский.
func IsEngByLoop(str string) bool {
for i := 0; i < len(str); i++ {
if str[i] > unicode.MaxASCII {
return false
}
}
return true
}
Раз мы уверены, что имеем дело только с 2 языками, то достаточно определить, являются ли все символы строки ASCII символами. Если да, то строка написана на Английском, если нет - то на каком-то другом (в вашем случае, это Русский).
Вот и все дела
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
package main
import "fmt"
func main() {
slice := []int{1}
fmt.Println(slice[1:])
}
Мы ведь обращаемся к элементу слайса с индексом 1, которого нет
Вот цитата:
"For arrays or strings, the indices are in range if 0 <= low <= high <= len(a), otherwise they are out of range. For slices, the upper index bound is the slice capacity cap(a) rather than the length."
Особенно важно последнее предложение
Ну и небольшой пример для полного понимания:
package main
import "fmt"
func main() {
slice := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
slice1 := slice[5:6]
slice2 := slice1[1:10]
fmt.Println(slice1, slice2, cap(slice2), len(slice2))
}
Подробнее
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
Repeater
, Controller
и Executor
.Также нужно сделать 1 модуль, который они будут импортировать с некоторым набором общих для них функций.
Как организовать структуру такого проекта?
main.go
под каждый сервис. Кладём их каждый в свою подпапку в директории, например cmd
.А для общих библиотек используем отдельную директорию, например
pkg
, и будем импортировать отсюда функционал во все 3 сервиса.cmd/
repeater/
main.go
controller/
main.go
executor/
main.go
pkg/
c-library/
clibrary.go
go.mod
go build ./cmd/repeater
go build ./cmd/controller
go build ./cmd/executor
main.go
:package main
import c_library "test/pkg/c-library"
func main() {
c_library.HelloWorld()
}
package c_library
import "fmt"
func HelloWorld() {
fmt.Println("HELLO WORLD")
}
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM