При этом, если функция будет работать больше указанного количества секунд, нужно прервать ее выполнение.
Таким образом нужно прервать выполнение этой функции
fun()
ниже, что можно сделать?
package main
import (
"fmt"
"sync"
)
func FibonacciRecursion(n int) int {
if n <= 1 {
return n
}
return FibonacciRecursion(n-1) + FibonacciRecursion(n-2)
}
func f(i int, wg *sync.WaitGroup) {
defer wg.Done()
fmt.Println(FibonacciRecursion(45 + i))
}
func fun() {
var wg sync.WaitGroup
for i := 0; i < 3; i++ {
go f(i, &wg)
wg.Add(1)
}
wg.Wait()
println("Function ended")
}
func main() {
fun()
}
С помощью
context
код выше можно переписать так:
package main
import (
"context"
"fmt"
"sync"
"time"
)
func main() {
timeLimit := time.Second * 10
ctx, cancel := context.WithTimeout(context.Background(), timeLimit)
defer cancel()
fun(ctx)
}
func isDone(ctx context.Context) bool {
select {
case <-ctx.Done():
return true
default:
return false
}
}
func FibonacciRecursion(ctx context.Context, n int) int {
if n <= 1 || isDone(ctx) {
return n
}
return FibonacciRecursion(ctx, n-1) + FibonacciRecursion(ctx, n-2)
}
func f(ctx context.Context, i int, wg *sync.WaitGroup) {
defer wg.Done()
fmt.Println(FibonacciRecursion(ctx, 45+i))
}
func fun(ctx context.Context) {
var wg sync.WaitGroup
for i := 0; i < 3; i++ {
wg.Add(1)
go f(ctx, i, &wg)
}
wg.Wait()
println("Function ended")
}
Такие вот дела
@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
go.mongodb.org/mongo-driver/mongo
?На локальном компьютере при отключении Mongo приложение в течение 30 секунд висит (видимо пытается подключиться).
Это время — оно задается в настройках клиента библиотеки или в самой Mongo или от чего еще зависит? Mongo поднята в контейнере, код подключения такой:
ctx, _ := context.WithTimeout(context.Background(), timeoutSecond*time.Second)
client, err := mongo.Connect(ctx, options.Client().ApplyURI(connString))
Сам запрос вот:
err := mr.client.Database(mr.dbName).Collection(mr.collName).FindOne(ctx, filter).Decode(&p)
context.WithTimeout
или context.WithCancel(ctx)
. Помимо этого, у вас имеется возможность настроить клиент к базе.У клиента есть ряд параметров с таймаутами, одни для выполнения одной операции, другие отвечают за время подключения к серверу (можно сказать время отклика сервера).
go channel
), который ожидает выполнения функции, либо завершения контекста, истечения timeout
этого запроса.select {
case <-ctx.Done():
return nil, ctx.Err()
case <-selectionState.timeoutChan:
return nil, wrapServerSelectionError(ErrServerSelectionTimeout, t)
case current = <-subscriptionCh:
}
срабатывает
<-selectionState.timeoutChan
, по умолчанию его значение 30 секундclient, err := mongo.NewClient(options.Client().ApplyURI("mongodb://localhost:27017"),
options.Client().SetConnectTimeout(time.Second * myTimeout),
options.Client().SetServerSelectionTimeout(time.Second * myServerTimeout))
@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
Мощная шпаргалка по Go, которая покрывает практически все темы
Если пролистать хотя бы по диагонали, есть отличный от нуля шанс пройти собеседование и получить оффер)
Что внутри?
├╼
Компилятор├╼
Пакеты├╼
Функции├╼
Управление памятью├╼
Операторы├╼
Управляющие структуры├╼
Объектноориентированность├╼
Интерфейсы├╼
Обработка ошибок├╼
Горутины (Goroutine)├╼
Проверка управления памятью├╼
Reflect ├╼
Добавление кода C├╼
GUI╰╼
Распределенные системы@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
При работе с базой данных миграция схемы является одной из важных задач, которую нам часто приходится выполнять на протяжении всего жизненного цикла приложения, чтобы адаптироваться к новым бизнес-требованиям.
И в этой статье речь пойдёт о том, как написать и запустить миграцию схемы базы данных в Golang, используя библиотеку
golang-migrate
, уверен, будет полезно@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
Держите полезные библиотеки для реализации схем аутентификации. Вы готовы? Их немало)
@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
ssl/tls
сертификатов. В коде есть фрагменты передачи данных из форм такого типаhttp://localhost:8080/?param1=value
Сейчас, без использования шифрования транспорта, можно получить значение
param1
такr.FormValue("param1")
Вопрос: если начать шифровать транспорт, сами данные останутся незашифрованны ведь? Или придётся изменить способ получения параметров из запроса и сперва эти параметры расшифровать?
package main
import (
"fmt"
"log"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Header().Set("Content-Type", "text/plain")
w.Write([]byte(fmt.Sprintf("param1=%s", r.FormValue("param1"))))
}
func main() {
http.HandleFunc("/", handler)
http.NewServeMux()
err := http.ListenAndServeTLS(":8080", "server.crt", "server.key", nil)
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
А вот команда генерации сертификатов:
openssl req -x509 -nodes -newkey rsa:2048 -keyout server.key -out server.crt -days 3650
Такие дела
@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
Самый простой способ писать хороший код заключается в том, чтобы не употреблять в своих программах «антипаттерны». Собственно, об этом и идёт речь в этой полезной статье
А вот некоторые из обсуждаемых антипаттернов:
// Не рекомендовано
type unexportedType string
func ExportedFunc() unexportedType {
return unexportedType("some string")
}
// Рекомендовано
type ExportedType string
func ExportedFunc() ExportedType {
return ExportedType("some string")
}
// Не рекомендовано
for _ = range sequence
{
run()
}
x, _ := someMap[key]
_ = <-ch
// Рекомендовано
for range something
{
run()
}
x := someMap[key]
<-ch
return
в функциях// Бесполезное выражение return, не рекомендовано
func alwaysPrintFoofoo() {
fmt.Println("foofoo")
return
}
// Рекомендовано
func alwaysPrintFoo() {
fmt.Println("foofoo")
}
break
в выражениях switch
// Не рекомендовано
switch s {
case 1:
fmt.Println("case one")
break
case 2:
fmt.Println("case two")
}
// Рекомендовано
switch s {
case 1:
fmt.Println("case one")
case 2:
fmt.Println("case two")
}
@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
ssh
, но через go get
/ go install
происходит ошибка:go: unrecognized import path "private.gitlab.ru/repositoryName": https fetch: Get "https://private.gitlab.ru/repositoryName?go-get=1": dial tcp 255.255.255.255:443(левый IP адрес): i/o timeout
Попытки установить хост данного репозитория себе в переменные
GONOPROXY
/ GOPRIVATE
/ GONOSUMDB
не помогли, ошибка остаётся той же.git config --global url."[email protected]".insteadOf "https://private.gitlab.ru"
git config --global url."https://${user}:${personal_access_token}@private.gitlab.ru".insteadOf"https://private.gitlab.ru"
После этого
go get
/ go install
будут работать с приватными репозиториями.@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
This media is not supported in your browser
VIEW IN TELEGRAM
О чём речь в статье?
@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
1
сделаем это пост полезным - выкладывайте в комментариях свои проекты, код, наработки, лучшие попадут в подборку.
сделаем это пост полезным - выкладывайте в комментариях свои проекты, код, наработки, лучшие попадут в подборку.
Пакет Go Mongo, поддерживающий операции по работе с документами и эффективным компоновщиком данных BSON с использованием различных типов данных.
BSON - бинарная форма представления простых структур данных и ассоциативных массивов (которые в контексте обмена называют объектами или документами)
go get github.com/chenmingyong0423/go-mongox
#golang #MongoDB
▪ Github
@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
go-daemon
:какой лимит по умолчанию на количество открытых дескрипторов файла в Go? Как его менять? И есть ли общепринятые рекомендации по их количеству?
ulimit -a
и ulimit -aH
в shell'е перед запуском вашего демона. Это быстро покажет текущие "мягкие" и (второй вызов) "жесткие" ограничения. При помощи ulimit
можно открутить мягкие ограничения до пределов жестких. Следует понимать, что ulimit
меняет только текущие лимиты, для шелла и всех программ, запущенных в этом шелле, поэтому после завершения сессии или даже в другом окне терминала значения останутся прежними./etc/security/limits.conf
и каталог /etc/security/limits.d/
, ограничение называется nofile
. Редактировать (а, иногда, и смотреть) эти файлы может только суперпользователь ("root"). Там задаются ограничения на отдельных пользователей или группы, применяемые на всю сессию данного пользователя, или всех пользователей определенной группы.sysctl
- это fs.nr_open
:/sbin/sysctl -n fs.nr_open
ему же соответствует файл
/proc/sys/fs/nr_open
getrlimit
/setrlimit
, которые можно звать из Go, используя FFI (примеры можно посмотреть здесь)@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
Основная идея — отделить интерфейс хранилища данных от его реализации. Тогда мы можем использовать различные реализации хранилища, обладающие одним интерфейсом
entity
/user
@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
Основная цель этого шаблона, кроме обучения — это снизить время на прототипирование небольших серверных задач на Go.
Шаблон включает в себя:
На изображении — UML-диаграмма последовательности запуска и остановки сервера
@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
./goprogram
1 29.06.2099 14:10
./goprogram
2 29.06.2099 14:12
./goprogram
3 29.06.2099 15:10
./goprogram
4 30.06.2099 14:10
При этом ни каких дополнительных файлов или записей не должно создаваться.
На Purebasic довольно просто такое реализовать:
• Скомпилированный бинарный файл создаёт свою копию.
• Записывает в конец файла число.
• Замещает оригинал изменённой копией.
• При повторном запуске выводит записанное число.
• Можно пример такой реализации на Go?
type persistent struct {
Magic [8]byte
Content int64
}
var p = persistent{
Magic: [8]byte{0xBA, 0xDD, 0xFA, 0xCE, 0xBE, 0xEF, 0xCA, 0xCE},
Content: 0,
}
func main() {
fmt.Println(p.Content)
const size = int(unsafe.Sizeof(p))
currentBuf := bytes.NewBuffer(make([]byte, 0, size))
err := binary.Write(currentBuf, binary.LittleEndian, p)
newP := p
newP.Content++
newBuf := bytes.NewBuffer(make([]byte, 0, size))
err = binary.Write(newBuf, binary.LittleEndian, newP)
currentBytes, newBytes := currentBuf.Bytes(), newBuf.Bytes()
self, err := os.OpenFile(os.Args[0], os.O_RDONLY, 0755)
selfBytes, err := ioutil.ReadAll(self)
i := bytes.Index(selfBytes, currentBytes)
copy(selfBytes[i:i+size], newBytes)
newSelf, err := ioutil.TempFile("", "selfmodifying")
_, err = newSelf.Write(selfBytes)
err = os.Rename(newSelf.Name(), self.Name())
err = os.Chmod(self.Name(), 0755)
}
@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
Вот задача — дано изображение в виде слайса байт, в которое нужно добавить метаинформацию вроде заголовков exif.
Практиески все библиотеки на Go дают возможно считать метаинформацию из файла, но не записать.
Благо, есть такая библиотека
go-exif
, которая умеет править или создавать новые exif-блоки: Немного подробностей про
go-exif
:@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
Инструмент для анализа размера зависимостей в скомпилированных бинарных файлах
Go.
• Github
@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM