Задать вопрос
  • Много исходящих запросов на сторонний API за короткое время и преобразование в JSON, справится ли node JS, или взять Go?

    @falconandy
    1. Можете начать с реализации отправки запросов и получения результатов, но результаты запросов просто игнорируйте без всяких преобразований. Сравните Go и Node между собой и с лимитом в 3 секунды. Если вышли за 3 секунды, думайте, как получать результаты быстрее или поднимайте лимит.
    2. Если вам нужна скорость, то нужно ли вам полноценное преобразование тело-запроса -> json -> объект -> БД? Можете ли вы обойтись более короткой цепочкой, например тело-запроса -> нужные поля -> БД?
    3. Для Go можете попробовать https://github.com/mailru/easyjson или аналоги, если структура объектов известна заранее. В этом случае преобразование json -> объект должно быть быстрее, чем со стандартной библиотекой.
    4. Для Go эта задача вполне в его нише - реализация должна быть простой. В общем случае что-то типа N горутин на выполнение запросов, M горутин для конвертации результатов, K горутин для записи в БД. Обычно K=1 и в этой горутине можно писать записи в БД пачками (batches), что быстрее, чем по одной записи.

    Весь день голову ломаю.

    За день уже могли бы реализовать на том, что знаете (nodejs) и если не устроит по результатам, попробовать Go.
    Ответ написан
    1 комментарий
  • Почему структура Golang работает не корректно при подключение в другом файле?

    includedlibrary
    @includedlibrary
    Потому что это приватное поле. Приватные поля начинаются с маленькой буквы, публичные - с большой. В рамках пакета вы можете обращаться к приватным полям структур этого пакета, но в других пакетах не можете этого делать
    Ответ написан
    Комментировать
  • Как правильно структурировать проект в Go?

    uvelichitel
    @uvelichitel Куратор тега Go
    habrahabr.ru/users/uvelichitel
    Вам в комментариях уже подсказали https://github.com/golang-standards/project-layout... Но этот документ не имеет официальной поддержки или методической силы. Это только волонтёрская попытка унификации.
    Подход команды разработчиков языка виден в сырцах компилятора и стандартной библиотеки.
    Рекомендованный и однозначно принятый сообществом layout не утверждён.
    Особые свойства есть у папок internal и vendor. Эти папки при сборке рассматриваются тулчейном go иначе чем другие. Особые свойства этих папок отражены в официальной документации.
    Ответ написан
    Комментировать
  • Как правильно устанавливать соединение с БД?

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

    Steel_Balls
    @Steel_Balls
    0KLRiyDQv9C40LTQvtGALiDQmNC00Lgg0L3QsNGF0YPQuQ==
    Здесь не язык надо выбирать, а правильно разрабатывать архитектуру.
    С правильной архитектурой неважно на чём написан бэк - на C#, Go, NodeJs или, простигосподи, на Kotlin.
    И вообще, в бэкенде обычно используется несколько языков. Python, JS, Go и C# одновременно - абсолютно нормально
    Ответ написан
    2 комментария
  • Что выбрать для бэкенда с нуля?

    uvelichitel
    @uvelichitel Куратор тега Go
    habrahabr.ru/users/uvelichitel
    Я, евангелист языка Go) Мне язык нравится и платят неплохо. Go быстрее чем Node.js, быстрее чем PHP.
    Но, хотел бы заметить:
    Вообщем есть проект написанный не мной, на PHP.

    переписывать работающий проект на другом языке должно быть явным побуждением стейкхолдеров.
    Ответ написан
    1 комментарий
  • В каких случаях использовать импортируемые поля в структуре go?

    @calculator212
    Я слышал, что желательно делать поля неимпортируемыми и использовать геттеры и сеттеры
    А где слышали?Вообще это не всегда верно, например даже стандартная библиотека для работы с csv там можно настраивать поля напрямую. В целом если у вас поля с простыми типами данных то в целом это не имеет особого смысла. Это имеет смысл если нужно работать с интерфейса или спрятать за ними часть сложной логики. Насколько я знаю эти идеи тащат люди из других языков, но паттерны которые распространены в Java или C# не всегда подходят для го поэтому не стоит все буквально воспринимать.
    На редите есть обсуждение этого вопроса тут.
    Ответ написан
    2 комментария
  • В каких случаях использовать импортируемые поля в структуре go?

    yellow79
    @yellow79
    Senior Software Engineer
    Что бы передавать данные в другие пакеты, которые ничего не знают о ваших геттерах/сеттерах =)
    Например encoding/json
    Ответ написан
    Комментировать
  • В каких случаях использовать импортируемые поля в структуре go?

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

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

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

    @sergomyaso
    Если ваш интерфейс реализует единственный метод, то почему бы и нет? На примере вашего News, который, допустим, имеет только метод Read(), то почему бы не назвать его NewsReader? Ну а в целом, везде необходимо включать здравый смысл, ведь это только рекомендации, а не железобетонные правила ;)
    Ответ написан
    5 комментариев
  • Как перейти с Python Django на Go?

    @calculator212
    Из похожего - это beego, но стоит прочесть https://habr.com/ru/post/444022/. Многие используют gin или что-то в этом духе(всё это обертки над стандартной net/htpp) или используют обертки над fasthttp.
    Подскажите как это сделать
    Если опыт в вебе есть, то просто пройти го тур, загуглить go roadmap и гуглить/читать книги/маны по нужному направлению.
    Ответ написан
    Комментировать
  • Как перейти с Python Django на Go?

    @sergomyaso
    Основная идеология Go - отсутствие фреймворков, поэтому сравнение с джанго будет немного странным. А в целом, советую запилить простое вэб приложения, используя простой http сервер и роутер, например, https://github.com/go-chi/chi . Для первых разов папочка example в помощь, там есть простые готовые штуки
    Ответ написан
    Комментировать
  • Как перейти с Python Django на Go?

    sergey-gornostaev
    @sergey-gornostaev Куратор тега Django
    Седой и строгий
    Читать учебники и документацию, практиковаться, гуглить. Всë, как с любым другим языком, Go не особенный.
    Ответ написан
    1 комментарий
  • Как лучше реализовать возвращение нескольких ошибок?

    @micronull
    Недавно как раз записал видео на тему обработок ошибок. Включая про возврат нескольких типов.

    Если вкратце.
    До 1.20 можно использовать multierr от uber.
    После 1.20 рекомендую использовать `errors.Join`.
    Ответ написан
    Комментировать
  • Golang не показывает что структура реализует интерфейс?

    @PapaStifflera
    Родился, вырос...
    Пишите в сапорт. Дженерики появились не так давно, видать не допилили еще до ума.
    Ответ написан
    Комментировать
  • Golang не показывает что структура реализует интерфейс?

    @dcaraxes
    meme engineer
    Видимо верхний ответ верный, пишите в саппорт либо попробуйте поставить другую версию GoLand. Скриншот из EAP Build #GO-223.8590, built on January 7, 2023
    63ba80a3e25df503632453.png
    Ответ написан
    1 комментарий
  • Почему после сборки приложения картинки не сохраняются?

    @falconandy
    1. Можно использовать embed, чтобы вшить картинку в бинарник.
    2. Но если посмотреть исходники beeep, то окажется, что библиотека работает с файлами и пока не умеет работать с массивом байт (Support for supplying image-data as a blob).
    3. Поэтому вы можете вшить картинку, но перед вызовом beeep.Notify вам надо будет сохранить вшитую картинку во временный файл и передать в beeep.Notify путь к нему.
    Ответ написан
    52 комментария
  • Как правильно парсить на Golang?

    разрешите за вас погуглить

    https://github.com/gocolly/colly/blob/master/htmle...

    func (h *HTMLElement) ChildTextgo(querySelector string) string


    https://github.com/gocolly/colly/blob/master/htmle...

    func (h *HTMLElement) ChildTexts(goquerySelector string) []string


    https://stackoverflow.com/questions/61498687/how-t...

    result := strings.Join(data, ",")
    fmt.Println(result


    How to build a web scraper with Go and Colly
    https://divrhino.com/articles/build-webscraper-wit...

    Building a web scraper in Go with Colly
    https://blog.logrocket.com/building-web-scraper-go...
    Ответ написан
    Комментировать
  • Как в процессе выполнения программы считывать вывод?

    Все гораздо проще. Вы можете сразу в stdout подложить буфер и смотреть в него при необходимости
    cmd := exec.Command("python", "script.py")
    stdoutBuf := bytes.NewBuffer(nil)
    cmd.Stdout = stdoutBuf
    if err := cmd.Run(); err != nil {
    	log.Println(err.Error())
    }
    
    fmt.Println(stdoutBuf.String())


    Или еще проще, если вам нужны и stdout и stderr вместе:
    cmd := exec.Command("python", "script.py")
    res, err := cmd.CombinedOutput()
    if err != nil {
    	log.Fatal(err)
    }
    fmt.Println(string(res))
    Ответ написан
    3 комментария
  • Как правильно взаимодействовать с каналами?

    То, что в канал данные пишутся медленнее, чем читаются, не должно вызывать никаких проблем при правильном подходе. У вас просто очень странно написан воркер, он на каждое событие запускает горутину и почему-то останавливается, если буфер канала пустой. Воркера надо по-хорошему останавливать, когда канал закрыт, а не пуст.

    Лучше сделать так
    package main
    
    import (
    	"bufio"
    	"fmt"
    	"os"
    	"sync"
    )
    
    func main() {
    	urls := make(chan string)
    	go fillChannel(urls)
    
    	// создаем группу для ожидания, того, что все воркеры завершены
    	wg := &sync.WaitGroup{}
    
    	for i := 0; i < 5; i++ {
    		// при запуске каждого воркера, увеличиваем счетчик в группе на 1
    		wg.Add(1)
    		go requestWorker(urls, wg)
    	}
    
    	// ждем, пока счетчик в группе не будет равен 0
    	wg.Wait()
    }
    
    func requestWorker(channel <-chan string, wg *sync.WaitGroup) {
    	// По завершении воркера счетчик в группе будет уменьшен на 1
    	defer wg.Done()
    	// Заодно пишем сообщение о завершении воркера
    	defer println("Worker stopped")
    
    	// Постоянно читаем из канала новые сообщения
    	// цикл автоматически завершится, когда канал закроется и буфер будет пуст
    	for url := range channel {
    		println(url)
    	}
    }
    
    func fillChannel(channel chan<- string) {
    	file, err := os.Open("data.txt")
    	defer file.Close()
    
    	if err != nil {
    		fmt.Println(err)
    		return
    	}
    
    	fileScanner := bufio.NewScanner(file)
    	fileScanner.Split(bufio.ScanLines)
    
    	for fileScanner.Scan() {
    		channel <- fileScanner.Text()
    	}
    
    	// закрываем канал, когда данные кончились
    	// в го принято, чтобы канал закрывал только тот, кто в него пишет
    	close(channel)
    }



    Этот паттерн называется worker pool. Мы пишем в канал все нужные данные и закрываем канал, когда данные кончились. Благодаря тому, что воркеры читают из канала через range, цикл просто выходит, когда канал закрыт и воркеры завершаются.
    WaitGroup используется для того, чтобы подождать, пока воркеры доработают последние данные.
    Ответ написан
    Комментировать