• Как вы обрабатываете ошибки в Web приложении на Go?

    dmnBrest
    @dmnBrest Автор вопроса
    Вы все правильно поняли! И подтвердили информацию которую я почерпнул в ходе изучения этого вопроса. Собственно так сейчас и делаю. Никаких panic и glog.fatal :)
    Подскажите такой вопрос. Это уже для интереса. Как бы в месте появления ошибки я руками записываю текстовое представление в glog.Error, который мне сохраняет информацию вместе с данными где я вызвал этот самый glog.Error в таком виде [E1107 18:20:58.734819 06405 server.go:39]. Но это данные не о самой ошибке, а именно о самом выводе, которые косвенно указывают на то место где произршла ошибка. А можно как-то эту информацию достать из самого объекта error, кроме его текстового представления?
  • Как вы обрабатываете ошибки в Web приложении на Go?

    dmnBrest
    @dmnBrest Автор вопроса
    Спасибо за ответ. Для себя заново открыл recovery :)
    Пример и идею обработки ошибок вашу понял, погуглил чтобы развить эту тему.
    Вот на такую интересное обсуждение натолкнулся
    www.reddit.com/r/golang/comments/2a1sie/when_to_ca...
    Большинство советует использовать панику в крайних случаях, request handlers к которым не относится.

    Для себя выработал решение:
    в месте ошибки записывать данные в лог и поднимать ошибку выше через return, а в контроллере отправлять http.Error(w, http.StatusText(500), 500) и прерывать выполнение.
    Вроде работает :) ошибки пишутся в лог (с нужными данными - где и когда), а пользователь получает свою 500.
  • Html sanitizer в Go?

    dmnBrest
    @dmnBrest Автор вопроса
    Интересный косяк. Не слышал про это. Надо будет запомнить на будущее, так как тоже приходится на ходу заниматься seo оптимизацией.
  • Какой самый красивый способ хостить свои проекты?

    dmnBrest
    @dmnBrest
    Это наверное вместе в Docker? Хотя на Docker стоит обратить внимание и без CoreOS. Очень интересное решение.
  • Html sanitizer в Go?

    dmnBrest
    @dmnBrest Автор вопроса
    "который на выходе и дает html-код с "проблемами"" Вы меня немного не так поняли :) . К самому редактору никаких претензий нет. Выбирал его долго и мучительно. "Проблемы" могут появиться благодаря нехорошим пользователям. Я не могу гарантировать что вместо вывод ckeditor мне не подсунут post запрос напрямую с интересными закладками в html. Вот собственно и нужна библиотека которая вычистит html и оставит только разрешенное (безопасное).
  • Html sanitizer в Go?

    dmnBrest
    @dmnBrest Автор вопроса
    Про CKEditor (раз так надо) + BBCode plugin отличный совет.
    Я так понимаю вы имеете в виду вот это - BBCode Output Format ckeditor.com/addon/bbcode
    Не знал что так можно.
    До этого во многих проектах сохранял полученный из CKEditor исходники в виде html и при выводе пропускал через htmlpurifier.org или для Rails через встроенный Sanitizer и потом естественно в template выводил без escaping. В таких случаях получаю исходное форматирование от автора статьи и защиту, если этот автор что надумает плохое.
    Тот же самый алгоритм сейчас перекладываю на Go.
    На счет использовать BBCode для хранения исходного кода - попробую этот вариант, один фиг у меня комментарии работают через bbcodes. Получится собрать все в одну кучу а не обрабатывать по разному статьи и комменты.

    ps. вы написали "CKEditor (раз так надо)". А почему "раз так надо". Что вы имели в виду под этим? Есть альтернативные метода создания функционала блога например. когда нужно предоставить пользователю удобное средство для написания статей?
  • Набор уникальных значений (Set) в Go?

    dmnBrest
    @dmnBrest Автор вопроса
    Спасибо за ответ. Для себя выбрал вариант через map. Из ссылки что привел Sergey Lerg узнал вот такой интересный момент - что вместо map[int]bool лучше использовать map[int]struct{}, потому что пустая структура не занимает место в памяти.
  • Как вы обрабатываете связи в Базе Данных в приложении на Go?

    dmnBrest
    @dmnBrest Автор вопроса
    @Tyranron, спасибо за пример.
    Отличная идея с uidsToArticles := map[int][]Article{} Действительно код стал лучше выглядеть.
    Вот эта часть тоже заинтересовала - IN (?"+strings.Repeat(",?")+")", uids... По ходу изучения сталкивался с полярными мнениями на счет этого куска кода. Одни говорят, что надо переменные из array передавать через биндинг по одной (как у вас). Другие говорят что надо страивать прямо в запрос (как у меня) и мол это хоть и не безопасно, но быстрее. Я взял за основу первый вариант, потому что у меня Postgres, а там placeholders вида $1, $2, $3 ... и получается что вот эта часть strings.Repeat(",?") растягивается на цикл.
    Спасибо за советы. Вы помогли пересмотреть мое отношение к процессу разработки на Go. Думаю дальше будет легче. Есть ли у вас еще какие-нибудь ресурсы в интернете с информацией по Go (может быть статьями) или другие сайты где вы предпочитаете общаться на тему Go, чтобы можно было пообщаться персонально? Toster хоть и хорош, но общения в комментариях к ответу как-то не очень выглядит :) Может быть какой форум?
  • Как вы обрабатываете связи в Базе Данных в приложении на Go?

    dmnBrest
    @dmnBrest Автор вопроса
    @Tyranron, не могли бы прокомментировать мои результаты. С join и без join. Как-то без join совсем не очень красивы выглядит. Неужели такая вермишель кода и циклов выгоднее одного join?

    c join:
    (пример из самого вопроса)

    с двумя запросами:
    articles := []Article{}
    err := DB.Select(&articles, "SELECT * FROM articles")
    uIds := []string{}
    for _, a := range articles {
    uIds = append(uIds, strconv.Itoa(a.UserId))
    }
    users := []User{}
    err = DB.Select(&users, "SELECT * FROM users WHERE id IN ("+strings.Join(uIds, ",")+")")
    if err != nil {
    glog.Fatalln(err)
    }
    usersMap := make(map[int]User)
    for _, u := range users {
    usersMap[u.Id] = u
    }
    for i, a := range articles {
    articles[i].User = usersMap[a.UserId]
    }

    Может скиньте свой пример какой-нибудь?
  • Как вы обрабатываете связи в Базе Данных в приложении на Go?

    dmnBrest
    @dmnBrest Автор вопроса
    @Tyranron спасибо за советы. Приму к руководству однозначно. По базам данных, по привычке из Rails использую Postgres. Почитаю что пишут про эту базу и сложные запросы.
  • Как вы обрабатываете связи в Базе Данных в приложении на Go?

    dmnBrest
    @dmnBrest Автор вопроса
    Это отличный подход. Я так уже более 3 лет делаю в Salesforce :) просто потому что там нет JOIN. Но вот пришел в мир plain sql и как бы хочется делать "красиво". Как раз до этого пытался узнать у гугла что лучше - один join из 2 таблиц или 2 запроса отдельно. Почему-то все советуют join, а не заниматься сбором parent ids в коде для подготовки второго запроса. Мне тоже проще так делать (в смысле 2 запроса) на код ложиться вообще замечательно.
    Спасибо за совет. Буду рыть в этом направлении.
    Если не сложно, приведите пример когда все-таки join лучше чем 2 и более отдельных запроса.
  • Как правильно передавать данные в http hendler на golang?

    dmnBrest
    @dmnBrest Автор вопроса
    "На мой взгляд это overingeniring." Супер. Опять вы подтвердили мои догадки :) Мне почему-то сразу показалось что это избыточно, но вот подтверждения найти не мог. Еще раз спасибо за помощь!
  • Как правильно передавать данные в http hendler на golang?

    dmnBrest
    @dmnBrest Автор вопроса
    Спасибо uvelichitel. Вы очень помогли с этим моментом, немного хаоса улеглось в голове :) . Конечно с &u все предельно ясно :).
    Еще тогда маленькое уточнение, чтобы совсем уж разобраться со всеми сомнениями.
    Такая замечательная штука html/template. Тот же самый момент - видел что проинициализированные templates засовывают в контекст чтобы потом в функции рендера достать из контекста и использовать.

    если я буду поступать как описал выше с DB, но только для такой ситуации?

    var templates map[string]*template.Template

    функция main:
    templates["home"] = template.Must(template.ParseFiles(...))
    templates["articleList"] = template.Must(template.ParseFiles(...))

    а в функции рендера
    templates[name].ExecuteTemplate(...)

    С этим проблем не возникнет. Пока что я склоняюсь к тому что все должно отработать нормально. Но что тут может случиться плохого в случае конкурентного запроса.
    Или может у вас есть свой рецепт или пример как правильно варить templates, поделитесь, буду признателен.

    Спасибо за помощь :)
  • Как правильно передавать данные в http hendler на golang?

    dmnBrest
    @dmnBrest Автор вопроса
    uvelichitel, спасибо за ответ. Но все как-то слишком сложно звучит. Извини, но я пришел с другой стороны в Go (из php, RoR, не из С++) поэтому приходится вникать в суть конкурентного выполнения запросов на пальцах. Подскажи на простом примере.

    есть у меня такая замечательная переменная
    var DB *sqlx.DB

    я в main делаю так:
    DB, err = sqlx.Connect("postgres", config.Database)

    Теперь во всех запросах я обращаюсь вот так:
    err := DB.Select(&u, "SELECT * FROM users")

    т.е. просто обращаюсь к переменной DB напрямую.

    Это нормально?

    Просто видел в одном примере, что перед тем как обратиться к переменной DB ее в middleware сначала кладут в контекст
    c.Env["DbMap"] = application.DbMap
    а потом из контекста в контроллере достают
    c.Env["DbMap"].(*gorp.DbMap)

    Если я правильно понимаю, то middleware выполняется в том же контексте (gourutine) что и сам handler.

    Как бы вы поступили в таком простом случае?

    (я пытаюсь разобраться в этом примере https://github.com/haruyama/golang-goji-sample , может это просто пример плохой для изучения? избыточный)
    Просто пока у меня получается делать приложение без всех этих бубнов с middleware и context и в дев режиме работает отлично. Хочу понять - какие будут косяки, если я не буду складывать все в контекст, чтобы потом использовать это в обработчике запроса.
  • Как правильно передавать данные в http hendler на golang?

    dmnBrest
    @dmnBrest Автор вопроса
    Извини, запятая к ссылке приклеелась. Вот нормальный вариант.
    elithrar.github.io/article/map-string-interface

    Подробно объяснить проблему пока не могу :) Сложно это все описать правильными терминами. Если по простому - то проблема в том чтобы обеспечить каждому запросу свой набор (копию) данных, а также обесчпечить безопасность при одновременном обращении к этим данным, чтобы не вызвать конфликта. Я пока это так вижу.
  • Как правильно передавать данные в http hendler на golang?

    dmnBrest
    @dmnBrest Автор вопроса
    Все! Я наверное начал понимать (вчитался в статью, которую привел в предыдущем примере) :) у меня "болезнь фреймворков". Я никогда не задумывался откуда все эти данные поступаю в запрос, потому что все данные для меня подготавливали фреймфворки, я только использовал. С Go это не пройдет и надо разбираться во всем на более низком уровне :).
  • Как правильно передавать данные в http hendler на golang?

    dmnBrest
    @dmnBrest Автор вопроса
    Вот тут про это написано elithrar.github.io/article/map-string-interface/, но я пока не могу уловить всю суть.
  • Как правильно передавать данные в http hendler на golang?

    dmnBrest
    @dmnBrest Автор вопроса
    ВОТ ИМЕННО! это я и имею в виду :))))) Да, так работает, НО почему никто так не делает а примерах и делают все всё через контекст? Вот что меня смущает. Если все так просто зачем нужны все эти танцы с бубном?
  • Как правильно передавать данные в http hendler на golang?

    dmnBrest
    @dmnBrest Автор вопроса
    Boniface спасибо за ответ. Но я имел в виду немного другое. Как создавать функцию это понятно. Не совсем понятно (вернее раньше было) как мне в этой функции обращаться к глобальным данным, например настройкам приложения, коннектору базы данных, тем переменным, которые я инициализирую на этапе запуска сервера в функции main. Просто в go все запросы выполняются параллельно в goroutines и везде пишут про то что при использовании глобальных переменных надо обеспечить "какую-то" безопасность от конфликтов во время одновременного выполнения.

    Вот простой пример - сделаю я структуру

    var a string

    в main ее заполню

    func main() {
    a := "hello"
    }

    Почему никто в примерах не обращается к переменно a в http hendler
    к этой переменной напрямую?
    например ,
    func HelloServer(w http.ResponseWriter, req *http.Request) {
    io.WriteString(w, a)
    }

    а создают какой-то context, ложат в этот context переменную и передают в функциою через параметры.