Ответы пользователя по тегу Go
  • Что выбрать с++, с или go для алгоритма?

    mirrr
    @mirrr
    Программист и просто хороший человек
    В С и С++ я начинающий, буду учиться по-ходу. Но 12 лет в Php+JS.

    Нет времени объяснять, используйте Go!
    Ответ написан
    1 комментарий
  • Что быстрее- хранить значения в памяти Golang или Redis?

    mirrr
    @mirrr
    Программист и просто хороший человек
    В какой ситуации Redis или похожие инструменты стоит использовать.

    Допустим, оперативные данные - цифра открытых соединений в определенный момент времени. Решается на уровне приложения просто, создаем переменную-счетчик, при открытии соединения увеличиваем, при закрытии - уменьшаем. Но с ростом нагрузки, приходится запустить несколько экземпляров приложения на нескольких серверах. Теперь в каждом экземпляре - разные счетчики и разные значения. Но если использовать внешнее хранилище - счетчик будет содержать общую цифру соединений.
    Второй случай - нужна сохранность данных в кеше при перезапуске/падении приложения. Например, тот-же счетчик, но уже не открытых соединений, а посетителей за сегодня. После каждого перезапуска терять данные нельзя.
    Третий случай - использование специфичных хранилищ, типа HyperLogLog в редисе.
    Ответ написан
    Комментировать
  • Какой Golang шаблонизатор выбрать и как подключить файлы динамически?

    mirrr
    @mirrr
    Программист и просто хороший человек
    В родных шаблонизаторах (text/template и html/template) нет функций подключения файлов, но есть возможность подключать другие шаблоны, добавленные, например, через template.ParseFiles или template.ParseGlob.

    Для начала парсим все шаблоны из каталога templates/ :
    funcs := template.FuncMap{
    	"SayHello": func(s string) string {
    		return "Hello"
    	},
    }
    
    t := template.Must(template.New("").Funcs(funcs).ParseGlob("templates/*.html"))


    Дальше используем:
    t.ExecuteTemplate(os.Stdout, "index.html", map[string]string{"title": "My site"})


    А внутри index.html пишем:
    {{template "login-form.html" .}}

    В FuncMap так-же можно добавить еще какую-нибудь функцию GetFile, которая будет читать файл и отдавать его содержимое в шаблон без обработки шаблонизатором.

    Но если использовать какой-нибудь gin-gonic, то все так:
    r := gin.New()
    r.LoadHTMLGlob("templates/*.html")
    
    r.GET("/", func(c *gin.Context) {
    	c.HTML(200, "index.html", map[string]string{"title": "My site"})
    })
    Ответ написан
    Комментировать
  • Как реализовать нормальные отношения между доками в mgo golang??

    mirrr
    @mirrr
    Программист и просто хороший человек
    В агрегациях монги, начиная с 3.2 есть аналог LEFT JOIN - $lookup. В mgo агрегации реализуются через Pipe. Маленький пример на коленке, в поле news при выборке попадают все новости автора:

    package main
    
    import (
    	"encoding/json"
    	"fmt"
    	"gopkg.in/mgo.v2"
    )
    
    type (
    	obj map[string]interface{}
    	arr []interface{}
    )
    
    func main() {
    	mongo, err := mgo.Dial("localhost")
    	if err != nil {
    		panic(err)
    	}
    
    	info := []obj{}
    
    	if err := mongo.DB("myDB").C("authors").Pipe(arr{
    		obj{"$match": obj{"banned": false}},
    		obj{"$lookup": obj{"from": "news", "localField": "_id", "foreignField": "authorID", "as": "news"}},
    	}).All(&info); err != nil {
    		fmt.Println("Error:", err)
    	}
    
    	printJSON(info)
    }
    
    func printJSON(t interface{}) {
    	j, _ := json.MarshalIndent(t, "", "\t")
    	fmt.Println(string(j))
    }
    Ответ написан
    Комментировать
  • Создание не используемой переменной, зачем?

    mirrr
    @mirrr
    Программист и просто хороший человек
    Я так поступаю, когда планирую в дальнейшем использовать переменную. Но после того как уже использовал изредка, но бывает, что забываю удалить "заглушку". Может здесь подобный случай?)
    Ответ написан
  • Почему mogolab не сохраняет объекты (golang, драйвер "gopkg.in/mgo.v2", )?

    mirrr
    @mirrr
    Программист и просто хороший человек
    package main
    
    import (
    	"fmt"
    	"gopkg.in/mgo.v2"
    )
    
    type (
    	person struct {
    		Name  string
    		Phone string
    	}
    )
    
    func main() {
    	session, err := mgo.Dial("localhost")
    	if err != nil {
    		panic(err)
    	}
    
    	session.SetMode(mgo.Monotonic, true)
    	col := session.DB("database").C("collection")
    
    	count, _ := col.Count()
    	fmt.Println(fmt.Sprintf("Messages count: %d", count))
    
    	err = col.Insert(&person{Name: "TestName", Phone: "+365756765"})
    }


    Результат:

    > use database
    switched to db database
    > db.collection.find()
    { "_id" : ObjectId("56bf67529ac5b6a0afcbe7b4"), "name" : "TestName", "phone" : "+365756765" }
    { "_id" : ObjectId("56bf67569ac5b6a0afcbe7b5"), "name" : "TestName", "phone" : "+365756765" }
    { "_id" : ObjectId("56bf67589ac5b6a0afcbe7b6"), "name" : "TestName", "phone" : "+365756765" }
    { "_id" : ObjectId("56bf675a9ac5b6a0afcbe7b7"), "name" : "TestName", "phone" : "+365756765" }


    В моем коде все работает. Что у вас не так, сложно понять, так-как код приведен не полностью. Но могу предположить, что в структуре Person названия полей не с заглавных букв начинаются и потому поля приватны.
    Ответ написан
  • Golang: пакет time. Возможно ли штатным образом проверить дату на корректность?

    mirrr
    @mirrr
    Программист и просто хороший человек
    Проблема (или нет) в том, что голанг распаршивает дату 30.02.2016 как 01.03.2016. И ошибку не выдает. Потому самый простой вариант - сравнить полученную дату с введенной.
    package main
    
    import (
    	"fmt"
    	"time"
    )
    
    func Check(format, date string) bool {
    	t, err := time.Parse(format, date)
    	if err != nil {
    		return false
    	}
    	return t.Format(format) == date
    }
    
    func main() {
    	fmt.Println(Check("02.01.2006", "29.02.2015")) // false
    	fmt.Println(Check("02.01.2006", "30.02.2016")) // false
    	fmt.Println(Check("02.01.2006", "31.04.2015")) // false
    	fmt.Println(Check("02.01.2006", "32.04.2015")) // false
    }
    Ответ написан
  • Правильно ли я делаю таблицу с правами?

    mirrr
    @mirrr
    Программист и просто хороший человек
    А я бы использовал битовую маску, тем более go прекрасно умеет с ними работать)
    type Rights int64
    
    const (
    	RightsAuth             = 1 << iota // 1 << 0 which is 0000000000000001
    	RightsRegs                         // 1 << 1 which is 0000000000000010
    	RightsBattlesInvasion              // 1 << 2 which is 0000000000000100
    	RightsBattlesSanctions             // 1 << 3 which is 0000000000001000
    	RightsBattlesGround                // 1 << 4 which is 0000000000010000
    	RightsMissionsLocation             // 1 << 5 which is 0000000000100000
    	// ...
    )


    Вот здесь более подробный пример: pastebin.com/jz6TZevq
    Ответ написан
    Комментировать
  • На чем написать высоконагруженный api сервер?

    mirrr
    @mirrr
    Программист и просто хороший человек
    Для golang даже код готовый дать могу )
    pastebin.com/qwXgUXdJ

    Но рекомендовать не буду) Просто для оценки поля боя)
    Ответ написан
    Комментировать
  • Развертывание web приложения на Go?

    mirrr
    @mirrr
    Программист и просто хороший человек
    Опишу свой способ, который перекликается со способом Алексей . Все это делается одним bash-скриптом, но распишу примерный алгоритм.

    1) Создаем юзера под которым будет работать приложение и переключаемся на него:
    useradd -s /bin/bash <имя_пользователя>
    su <имя_пользователя>


    2) Генерируем новый ключ для деплоя
    ssh-keygen -t rsa -C "<имя_пользователя>@<домен_сервиса>"
    cat ~/.ssh/id_rsa.pub

    Например, в gitlab добавляем этот ключ Project>Settings>Deploy Key

    3) Клонируем приложение и собираем приложение
    cd ~
    git clone ssh://______.git app 
    # здесь не буду расписывать, можно устанавливать через go get и т.д. способы отличаются
    # для go get нужно прописать $GOPATH в .bash_profile


    4) Создаем systemd service
    exit #выходим из-под юзера
    nano /etc/systemd/system/<service_name>.service

    Вписываем:
    [Unit]
    Description=<description>
    
    [Service]
    Restart=always
    RestartSec=10
    EnvironmentFile=-/<service_path>/env
    WorkingDirectory=/<service_path>/appDir
    ExecStart=/<service_path>/appDir/appName
    LimitNOFILE=524576
    LimitNPROC=524576
    User=<user>
    Group=<userGroup>
    StandardOutput=syslog
    StandardError=syslog
    SyslogIdentifier=<service_name>
    
    
    [Install]
    WantedBy=multi-user.target


    5) Запускаем сервис и ставим в автозагрузку:

    systemctl start <имя_сервиса>
    systemctl enable <имя_сервиса>


    Посмотреть статус:

    systemctl status <имя_сервиса>

    6) Разрешаем просмотр логов и перезапуск сервиса под созданным пользователем
    Добавляем в /etc/sudoers строчки:

    Defaults:<имя_пользователя> !authenticate
    <имя_пользователя> ALL=/usr/bin/systemctl restart <имя_сервиса>, /usr/bin/systemctl stop <имя_сервиса>, /usr/bin/systemctl start <имя_сервиса>, /usr/bin/journalctl


    Теперь эти операции не будут требовать пароля:
    sudo journalctl -f  -u <имя_сервиса> 
    sudo systemctl stop <имя_сервиса>
    sudo systemctl start <имя_сервиса>
    sudo systemctl restart <имя_сервиса>


    7) настраиваем виртуальный хост nginx для проксирования на порт приложения, если требуется:
    server {
        listen 80;
        server_name site.ru;
    
        client_max_body_size 256m;
        access_log  /var/log/nginx-site-acc;
        error_log /var/log/nginx-site-err;
        log_not_found off;
    
        location ^~ / {
            proxy_pass http://localhost:<порт_приложения>;
            proxy_set_header Host $host:$server_port;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_buffer_size 16k;
            proxy_buffers 32 16k;
            proxy_connect_timeout 300;
            proxy_send_timeout 300;
            proxy_read_timeout 300;
        }
    
        location ^~ /files {
            alias /home/<имя_пользователя>/app/some_files;
        }
    }
    Ответ написан
    Комментировать
  • Есть ли альтернативные пакеты для html шаблонов(написал свой)?

    mirrr
    @mirrr
    Программист и просто хороший человек
    Я бы отдавал html как статику, а рендер вынес на сторону клиента, используя микро-темплейтер типа doT.js или swig
    Ответ написан
  • Как сделать эту функцию не такой страшной?

    mirrr
    @mirrr
    Программист и просто хороший человек
    func dataValid(result []string) bool {
    	return v.IsLogin(result[0]) && isLoginAvailable(result[0]) &&
    		v.IsEmail(result[1]) && isEmailAvailable(result[1]) &&
    		v.IsPass(result[2])
    }
    Ответ написан
    3 комментария