Ответы пользователя по тегу Go
  • Как проверить наличие пользователя в БД?

    DollyPapper
    @DollyPapper
    У вас какая-то странная логика получилась.
    _, err := db.Query("SELECT chat_id FROM telegram WHERE chat_id=?", chatID)

    если этот запрос отработает без ошибок (в т.ч. если результат будет не пустой), то err будет = nil, следовательно выполнится блок else и создастся пользователь. Т.е. буквально, если уже есть такой пользователь, то вы создаете нового.
    Вам нужно что-то типа
    _, err := db.Query("SELECT chat_id FROM telegram WHERE chat_id=?", chatID)
    if errors.Is(err, sql.ErrNoRows) {
    // создаем пользователя
    } else {
    fmt.Println("Пользователь уже есть в базе данных")
    }
    Ответ написан
  • Какой гайд поможет делать авторизацию на сайте golang?

    DollyPapper
    @DollyPapper
    Во первых аутентификацию. Авторизация это про проверку прав.
    Если без REST API, то классика это принимать через POST запрос данные с формы.
    Вот статья
    Если кратко:
    Делаете ручку /signin, которая проверяет пароль присланный пользователем с хешем паролей в базе данных (ну или где вы храните данные)
    Если всё ок, создаете сессию, сохраняете сессию где нибудь в хранилище (опять же это может быть база данных, может быть ин мемори, есть библиотеки для этого, погуглите, да хоть в памяти приложения в мапе храните)
    Далее ID сессии записываете в куки и посылаете ответ пользователю в заголовком Set-Cookie sessid="session_id", где session_id это айди который вы раньше сгенерили.
    А далее пользователь ходит на ваш сайт, и какая нибудь мидлвара берет из запроса куки, берете оттуда id сессии, ищет этот айди в хранилище. Если нашла, то пропускает запрос дальше, если нет - 401 Unauthorized.
    Ну в статье вобщем всё подробно описано.
    Ответ написан
    Комментировать
  • Как правильно устанавливать соединение с БД?

    DollyPapper
    @DollyPapper
    Если вы будете пул создавать каждый раз при запросе в каждой функции, то какой тогда смысл от пула? Пул в go это своего рода синглтон, он создается один раз и далее распространяется по всему приложению. Очевидно, что если каждый раз будет новый инстанс пула, то никакой защиты от переполнения коннектов мы не получим. Итого: пул создается один раз, далее во всех остальные части программы он передается как вам удобно, через DI напрямую в фукнцию, в конструктор обьекта или еще как.
    Ответ написан
    Комментировать
  • В каких случаях использовать импортируемые поля в структуре go?

    DollyPapper
    @DollyPapper
    Смысл делать поля экспортируемыми есть в очень редких случаях. Один из таких случаев например маршалинг (json/yaml/etc), без экспортируемых полей библиотека просто не сможет засеттить значение в поле. Другие дело обстоит с сущностями (обьектами/структурами вашей предметной области). В случае сущности эта самая сущность должна скрывать свое внутренее состояние и не позволять изменять его извне. Приведу банальный пример:
    type User struct {
        Name string
        Age    int
    }

    И сеттеры геттеры к ней.

    Далее допустим есть бизнес правило, что у вас можно регистрировать пользователей строго старше 18 лет. Как вы будете контролировать, что нельзя назначить возраст < 18 лет? Да никак, с экспортируемыми полями это невозможно. Почитать на эту тему можно погуглив про инкапсуляцию и information hiding. В данном конкретном случае геттеры и сеттеры наверное будут более подходящими. В сеттерах можно прописать условие, что возраст должен быть строго больше 18 лет. Однако может быть и такой случай, что сущность не должна вообще более изменяться после создания. Для этого в ООП языках, чтобы задать первоначальные значения существуют конструкторы. В го нет конструкторов, т.к. нет понятия класса, но нам ни что не мешает создать обычную функцию порождающую обьект юзера, и засеттить значения возраста и имени в этой фкнции.
    Ответ написан
    Комментировать
  • Можно ли изменять неимпортируемые поля структуры в других пакетах программы?

    DollyPapper
    @DollyPapper
    Возможно уже неактуально, но.
    Не следует строго следовать мантрам про "глобальные переменные это плохо". Иногда это необходимо. Делаете из своего кеша синглтон (как его правильно делать в го можно посмотреть в инете). Переменная инстанс самого обьекта кэша будет лежать на уровне пакета кэша и будет неэкспортируемой. А сама New будет возвращать либо кэш, если он уже ранее был создан, либо тот инстанс который был создан. Так например pgxpool устроен ЕМНИП.
    Ответ написан
    Комментировать
  • Как сделать видимость в 2-х разных пакетах структуры из 3-го?

    DollyPapper
    @DollyPapper
    А зачем вы вообще сделали алиас на тип p3.SM? Возвращайте просто p3.SM из p1 somefunc и принимайте p3.SM в p2 anotherfunc. Ну либо если вам зачем то прям понадобился этот алиас, то приведите тип anotherfunc(p3.SM(SM)).
    UPD: в Go нет динамической диспетчеризации. То что вы пытаетесь сделать - создать подтип с помощью алиаса. В Go это не прокатит.
    Ответ написан
  • Как организовать архитектуру кода для взаимодействия с БД в Golang?

    DollyPapper
    @DollyPapper
    Тут все зависит от того как вам удобно, кто бы что не говорил, нет единого стандарта нужно/не нужно. Я наоборот чаще вижу что вместо прямого источника данных подают репозитории в сервисы. И сам так делаю. Это банально удобней тестировать.
    Ответ написан
    Комментировать
  • Как задать тип для структуры, где может быть массив или строка?

    DollyPapper
    @DollyPapper
    В Golang есть такое понятие как дженерики.

    В вашем примере код может выглядеть как нибудь так:
    type StringOrStrings interface {
    	string | []string
    }
    
    type DataStruct[T StringOrStrings] struct {
    	Data T
    }

    StringOrStrings interface в данном случае выступает как ограничитель типа. Далее советую подробней ознакомится с документацией по Generics на оф. сайте Go.
    Ответ написан
    Комментировать