Задать вопрос
Ответы пользователя по тегу Go
  • Как в Go происходит неявное удовлетворение интерфейсу?

    Интерфейс в Го, это структура с двумя полями.
    1. Указатель на данные (в вашем случае на структуру User с age и name)
    2. Указатель на таблицу виртуальных методов.
    В таблице виртуальных методов как раз перечислены методы, которые реализованы на структуре и на рантайме через нее Го понимает, что можно вызывать, а что нельзя.

    В статье https://habr.com/ru/articles/856272/ можете почитать подробнее, там описано как работает itab (таблица виртуальных методов).


    Можно ли даже при созданном вручную String() использовать метод String() из стандартной библиотеки?


    String в стандартной библиотеке это не метод на структуре. Это код, который через рефлексию смотрит что ему пришло и вызывает соответствующий форматтер. Одно из условий, которые он проверяет, это как раз, имплементит ли объект интерфейс Stringer, поэтому в вашем коде вызывается этот метод.
    Использовать стандартный форматтер структуры получится разве что костылями, дергая вручную более "тупые" методы стандартной библиотеки или через пакет reflect вытащить данные из структуры.

    Как это вообще может помочь в целом в работе и какие есть юзкейсы для этого?


    Слишком общий вопрос, обычно интерфейсы используются как вариант полиморфизма и как способ уменьшения связанности кода (это чтобы не импортить какой-то пакет из своего пакета, а вместо этого принять абстрактный объект, который умеет определенные методы). Еще так избавляются от циклических зависимостей.
    Ответ написан
    1 комментарий
  • Как должна выглядит правильная структура "внедрение зависимостей"?

    1. Интерфейсы лучше всего объявлять в тех местах, где они используются. То есть, внутри слоя бизнес-логики.
    2. Репозиторий не должен возвращать/принимать никаких транспортно-специфичных типов (никаких *gorm.DB, пакета sql и прочих). Только структуры слоя бизнес-логики.
    3. Репозитории лучше всего разделить, если у вас данных идут из монги, постгреса и редиса, это будут 3 разных репозитория, не надо их пытаться объединить под один интерфейс.
    4. Передавать все зависимости чтобы сделать "внедрение" лучше всего в конструкторе. somepkg.New(pgRepo, mongoRepo). Внутри somepkg у вас будут определены интерфейсы под эти все репозитории, причем там будут только те методы, которые используются внутри этого пакета. В другом someotherpkg у нас будет определен уже другой интерфейс, содержащий методы, которые использует someotherpkg. Таким образом лучше видно что откуда используется и сохраняется чистота кода.
    5. Делите обязательно все на слои, хендлеры импортят бизнес-логику, репозитории импортят бизнес-логику, но бизнес-логика не импортит ничего из хендлеров и репозиториев (для этого как раз интерфейсы и нужны). В итоге главная логика будет очень простая и изолированная от бойлерплейта транспортных слоев, не нужно будет переписывать тесты если что-то изменится в транспорте.
    Ответ написан
  • Как установить драйвер mysql для golang?

    У вас проект не инициализирован, надо сделать go mod init имя
    Вы пытаетесь добавить модуль как это делалось лет 7 назад, когда в Го не было модулей. Теперь надо все проекты делать через модули.
    https://go.dev/blog/using-go-modules

    После того как сделаете init, добавляйте модуль через
    go get github.com/go-sql-driver/mysql@latest
    Ответ написан
    Комментировать
  • Golang путь как использовать паттерн Фабрику без наследования?

    Фабрику вообще не принято использовать в Го. Используйте вместо нее обычные конструкторы. Функцию New() в пакете, где у вас описан пользователь.

    Когда с пользователем нужно что-то сделать, делайте это не методом самого типа пользователя, а функцией в пакете, который будет отвечать за проведение действий с пользователями. Если у вас разные пользователи и надо делать какую-то общую логику с ними, то пусть функции пакета, где будут действия с пользователем, принимают интерфейс, а не конкретный тип.

    В интерфейсе перечисляйте только нужные для действий методы, а не все методы пользователя.
    Ответ написан
  • Не понимаю как работает цикл?

    В вашей задаче нет циклов, почему в вопросе упоминается цикл?

    У вас main написан так, что передаваевая в checkNil переменная никогда не будет nil.

    Внутри checkNil вы перепутали равенство с неравенством. v != nil значит "v не равно nil", а у вас в этом случае выводится, что переменная пустая, хотя должно быть наоборот.
    Ответ написан
    Комментировать
  • Не создается функция. Как это можно исправить?

    У вас не создан файл go.mod в корне проекта. Выполните команду
    go mod init github.com/yourname/yourproject
    в корне проекта. Адрес может быть любой, принято указывать адрес вашего репозитория, но можете указать и несуществующий урл. Будет работать если указать не урл, а просто goproject, но так не принято и форматтеры кода будут путать ваш пакет со стандартной библиотекой.

    У нас в файле shapes.go почему-то package goproject, хотя должен быть package utils

    Потом замените ваш импорт на
    import github.com/yourname/yourproject/utils""
    Ответ написан
    4 комментария
  • В чем смысл использования Golang как веб сервер?

    Го намного проще многих других языков, соответственно проще читать и понимать чужой код, что ценится в больших компаниях, где работает много людей. Плюсом ценится то, что довольно сложно выстрелить себе в ногу.

    Тесты есть разные, Го примерно идет в ногу с Джавой и Шарпом, особенно в случае многопоточных нагруженных серверов. А если посмотреть сколько он потребляет при этом памяти, то даже выходит вперед по эффективности.

    На Го очень просто писать многопоточность и асинхронность, не нужно думать об await-ах, каждая горутина имеет свой стек, что снимает с программиста много головной боли. Вся стандартная библиотека и большой набор библиотек с гитхаба из коробки поддерживают асинхронность и потоковую обработку данных, работать с этим сильно проще, чем в других языках. Соответственно, сложнее накосячить.

    Но абстракций на Го очень мало, по сравнению с той же Джавой, он довольно бедно выглядит (что и дает простоту чтения кода). Это является минусом в определенных ситуациях, поэтому на Го стараются писать небольшие сервисы.

    В итоге, легковесность горутин, легкость работы с ними и асинхронная модель из коробки (не создается тред на каждую рутину, а наоборот, рутины обрабатываются разными тредами по необходимости) привели к тому, что ниша Го это сервисы, которые упираются в ожидание ресурсов от каких-то внешних систем по сети. То есть, идеальный кейс для веб-сервера, который собирает под капотом инфу с БД и других сервисов. По сути такой сервис большую часть времени ждет ресурсов по сети, в Го это ожидание сделано очень эффективно.
    Ответ написан
    Комментировать
  • Импортирование доменных моделей другого сервиса?

    Импорт grpc-контрактов будет корректным.

    Импорт доменных моделей — нет. Потому что доменные модели должны быть независимыми внутри самого сервиса.
    Ответ написан
    Комментировать
  • Opentelemtry +?

    Prometheus это про метрики

    Grafana это тоже про метрики

    Судя по коду, вы сделали поддержку трейсинга в вашем приложении, а чтобы смотреть трейсы, нужно развернуть интерфейс Jaeger. https://www.jaegertracing.io/

    Есть статья на эту тему https://habr.com/ru/articles/710644/
    Ответ написан
  • Докер ограничивает размер загружаемого на бекенд файла?

    Докер ничего не знает про http, он только пробрасывает tcp-коннекты до вашего приложения. Так что проблема точно где-то в вашем коде. Скорее всего какой-то из конфигов локально у вас подключается, а в докер не пробрасывается, поэтому какие-то из ограничений внутри приложения не снимаются.

    502 Bad Gateway обычно вылезает, когда ваше приложение запрос куда-то перенаправляет. Вы с файлом что делаете, сохраняете на диск или куда-то отправляете?
    Ответ написан
  • Как сохранить нули после запятой в типе float64?

    Если тип поля сделать json.RawMessage, то оно не будет меняться. Удобно, когда вам не нужно само число, но надо чтобы оно просто сохранилось при приеме-передаче структур.

    https://go.dev/play/p/egy2GXVB-5p

    код
    package main
    
    import (
    	"encoding/json"
    	"fmt"
    )
    
    type testStruct struct {
    	ID    string          `json:"id"`
    	Type  string          `json:"type"`
    	Value json.RawMessage `json:"value,omitempty"`
    }
    
    func main() {
    	var msg testStruct
    
    	json.Unmarshal([]byte(`{"type": "test", "id": "testID", "value": 123.00}`), &msg)
    
    	output, _ := json.Marshal(msg)
    
    	fmt.Println(string(output))
    }
    Ответ написан
    Комментировать
  • Как конвертировать .ogg в другой аудио-формат (.mp3, .wav) на Go?

    func main() {
    	cmd := exec.Command("ffmpeg", "-i", "input.ogg", "output.mp3")
    	res, err := cmd.CombinedOutput()
    	if err != nil {
    		fmt.Println(string(res))
    		fmt.Println("error executing command:", err)
    		os.Exit(1)
    	}
    }


    Естественно, на системе должен быть установлен ffmpeg, потому что тут вызывается внешняя программа.
    Ответ написан
    Комментировать
  • Как можно регулярным выражением получить три вхождения в многострочном тексте?

    Тут лучше без регулярок, будет эффективнее: https://go.dev/play/p/7Ae-T6O0YmD

    text := `Мы оба влюблены в один и тот же сон,
    Нас вынесла волна — и укатилась с шумом.
    Ты ль жарче влюблена, иль я страстней влюблен,
    Какое дело нам! Мы не поверим думам! 15 июня 1903
    Информация сайта: https://domain.tdl/?name=asdasdasd
    `
    
    parts := strings.Split(text, "Информация сайта: ")
    
    fmt.Println(parts[0])
    fmt.Println(parts[1])


    Если очень хочется регуляркой, тогда так: https://go.dev/play/p/pJ0mtx4gWPC

    re := regexp.MustCompile(`(?s)^(.+)Информация сайта: (.+)$`)
    
    matches := re.FindStringSubmatch(text)
    
    fmt.Println(matches[1])
    fmt.Println(matches[2])
    Ответ написан
    1 комментарий
  • Как писать микросервисную архитектуру?

    Вы не сможете себе в портфолио добавить микросервисную архитектуру просто написав ее в пет-проекте. Настоящие микросервисы можно пощупать только на масштабах больших компаний и их инфраструктуре, так что устраивайтесь джуном/стажером в какой-нибудь Авито или Озон.

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

    Сделайте лучше хороший проект-монолит, отработайте навыки языка, БД, развертывания, гита, итд... на одном проекте. Будет гораздо полезнее.
    Ответ написан
    2 комментария
  • Как вытащить поля из запроса в pgx?

    https://pkg.go.dev/github.com/jackc/pgx
    Самый первый пример из верха документации
    var name string
    var weight int64
    err := conn.QueryRow("select name, weight from widgets where id=$1", 42).Scan(&name, &weight)
    if err != nil {
        return err
    }


    Только поля замените на свои

    В пятой версии добавились еще другие способы https://pkg.go.dev/github.com/jackc/pgx/v5#hdr-Que...
    Ответ написан
    Комментировать
  • Если в glang перемнная передана в func, то она там живёт сомостоятельно или в пямяти 1 адрес?

    В Го по-умолчанию переменные передаются по значению (то есть, копируются на стеке), но есть нюансы.

    1. Мапы и каналы всегда передаются по указателю.
    2. У слайса на стеке только дескриптор, так что он копируется, но данные, на которые слайс указывал, остаются там же в памяти, где и были.
    3. Если вы явно передаете указатель, то тут все очевидно.
    4. У интерфейсов копируется дескриптор, но т.к. в дескрипторе указатель, то тут все как со слайсами.
    Ответ написан
    Комментировать
  • Почему не работает код Go?

    Код же выводит на экран те строки, которые были написаны вами более 1 раза. А в приведенном скриншоте вы каждое число по одному разу только ввели.

    Проверил у себя, все работает:
    $ go run main.go
    hello
    Hi
    John
    hello
    John
    Paul
    John
    ^D
    2	hello
    3	John


    hello я написал два раза, поэтому там цифра 2, а John написал 3 раза. Остальные слова только один раз, поэтому их нет в выводе
    Ответ написан
    5 комментариев
  • В стандартной библиотеке go есть ли инструменты для работы с многомерными срезами/массивами?

    В стандартной библиотеке — нет. Но есть сторонние библиотеки вроде https://pkg.go.dev/gonum.org/v1/gonum/mat или https://github.com/james-bowman/sparse

    Если вы решаете задачи на алгоритмы, то вам лучше как раз без таких библиотек, которые в одну строчку делают задачу (потому что в библиотеке кто-то до вас уже написал агоритмы).

    Если же по работе нужно для решения проблемы, то берите одну из библиотек, которые я предложил выше.

    Ведь без инструментов, тут нужен iq минимум 150


    Это вам так кажется, потому что первый язык и вы только начинаете разбираться. На самом деле такие задачи без проблем решаются на чистом го.
    Ответ написан
    Комментировать
  • Почему я получаю ошибку invalid operation: err (variable of type Error) is not an interface при проверке типа переменной?

    https://go.dev/play/p/eDi3J3Zzcdg

    package main
    
    import "fmt"
    
    type MyError struct {
    	Message string
    }
    
    func (e MyError) Error() string {
    	return e.Message
    }
    
    func (e MyError) Smth() {
    }
    
    type SomeInterface interface {
    	Smth()
    }
    
    func main() {
    	var err SomeInterface
    	err = MyError{"Something went wrong"}
    
    	// Проверяем, реализует ли err интерфейс error
    	if _, ok := err.(error); ok {
    		fmt.Println("err реализует интерфейс error")
    	} else {
    		fmt.Println("err НЕ реализует интерфейс error")
    	}
    }


    У вас получилось, что тип переменной err это структура, но нужно чтобы тип был каким-нибудь интерфейсом.

    В моем примере я создал интерфейс SomeInterface и добавил вашему типу метод, чтобы он этому интерфейсу удовлетворял. Теперь данный ассершн имеет смысл.

    P.S. С пустым интерфейсом тоже работать будет https://go.dev/play/p/Yz0M1Wzopua
    Ответ написан
    Комментировать
  • Какой фреймворк для Go изучать в 2024 году?

    Если http:
    Взять какой-нибудь хороший роутер, например https://github.com/julienschmidt/httprouter
    И на его основе сделать врапперы и мидлвари под себя по необходимости.
    Если работаете в какой-то конторе, то там уже должен быть фреймворк для микросервисов, заточенный под инфраструктуру компании. Потому что если сервисы делаются все по-разному, это беда.

    Если grpc:
    Особых вариантов нет, нужно использовать protoc.
    При необходимости подключить плагины, чтобы был сваггер и гейтвей в http
    github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway
    github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2

    Почему не предлагаю какой-то большой конкретный фреймфорк? Если бы вы сказали, что веб-приложения будете писать, можно было бы посоветовать что-то типа gin, но вы сказали про микросервисы. С ними такая специфика, что надо как конструктор собирать себе стек под задачу, иначе будет неудобно.
    Ответ написан
    3 комментария