Задать вопрос
  • Как преобразовать interface в string?

    https://go.dev/play/p/-aB5SS1amav
    package main
    
    import (
    	"fmt"
    	"log"
    )
    
    func main() {
    	code := map[string]interface{}{
    		"test": "test",
    	}
    
    	// извлекаем interface{} из мапы внутри которого строка
    	ifaceStr := code["test"]
    
    	// извлекаем строку из interface{}
    	str, ok := ifaceStr.(string)
    	if !ok {
    		log.Fatal("it's not a string")
    	}
    	fmt.Println(str)
    }


    Но почему бы вам не делать анмаршал в map[string]string сразу? Чтобы не конвертить лишний раз?
    Ответ написан
  • Можно ли использовать значение переменной как название структуры?

    Так делать не стоит, в го это решается другими способами. Вы пытаетесь переносить подход из скриптовых языков в го, так это не работает.
    Ответ написан
  • Как отдавать статику через julienschmidt/httprouter?

    r.Handler("GET", "/", fServer)
    Этот шаблон значит полное совпадение с корнем, поэтому у вас 404 на все вложенные страницы. Чтобы этого избежать сделайте так:

    r.Handler("GET", "/*filepath", fServer)
    Ответ написан
    3 комментария
  • Golang выдает ошибку, что делать?

    Вам компилятор четко пишет
    main redeclared in this block {строка 8 столбец 6 }
    previous declaration at ./hello.go:18:6

    Перевожу: функция main написана несколько раз, второй раз она встречается в файле hello.go на 18 строчке.
    Видимо, у вас в одной папке несколько файлов и в нескольких из них есть функция main. Так делать нельзя, все, что находится в одной папке, го считает одним пакетом.

    Что касается второй ошибки, отправляйтесь изучать основы синтаксиса языка, иначе далеко так не уедете. У вас лишние запятые в конце списка параметров и в конце списка переменных.
    Ответ написан
    9 комментариев
  • Запутался с установкой golang, что делать?

    потом я хотел настроить перменную GOPATH, а там как я понял надо указать путь до ГО и там выбрать папку scr.


    Нет, вы пользуетесь каким-то странный старым руководством. Если из пакетов ставите, то у вас уже всё нужное есть. Никакой GOPATH уже давно прописывать не надо.
    Ответ написан
    Комментировать
  • Как через os/exec запустить сторонний exe файл в GoLang?

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

    Несколько примеров:
    path := `c:\Program files\some program\program.exe`
    // аналогично вызову в консоли start "c:\Program files\some data"
    cmd := exec.Command("start", path)
    ......
    
    // аналогично вызову в консоли "c:\Program files\some program\program.exe"
    cmd := exec.Command(path)
    ......
    
    // аналогично вызову в консоли some_prog.exe -flag1 value1 -flag2 value2
    cmd := exec.Command("some_prog.exe", "-flag1", "value1", "-flag2", "value2")
    ......


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

    Кстати, если вам просто нужен полный ответ команды stdout+stderr, можете использовать метод cmd.CombinedOutput(). Он выполнил программу, дождется ее завершения и вернет полностью то, что она писала в консоль.
    Ответ написан
    7 комментариев
  • Как вы решаете проблему циклических импортов?

    orders и payments должны лежать внутри одной модели.
    Если кода много, то можете вынести эти структуры в отдельный пакет, посвященный только внутренним структурам данных, это и будет та самая одна модель.
    пакет structures: типы orders и payments
    пакет orders: импортирует structures
    пакет payments: импортирует structures

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

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

    Старайтесь никогда не использовать пустой интерфейс (interface{}), только в самых крайних случаях.
    Тут вам нужно просто изменить тип мапы на map[string][]func(string, interface{})

    Не знаю, почему shortName у вас тоже имеет тип interface{}, его бы изменить на конкретный тип или конкретный интерфейс. Тогда код станет еще понятнее и удобнее.
    Ответ написан
    Комментировать
  • Как ускорить работу кода?

    Для таких целей отлично подходит паттерн "worker pool"
    https://gobyexample.com/worker-pools

    Создаете воркеров столько, сколько параллельно урлов хотите обрабатывать. Отправляете в канал не слайс урлов, а урлы по-одному. Каждый воркер берет из канала свой урл и все они параллельно обрабатывают разные урлы.
    Ответ написан
    1 комментарий
  • При запуске микросервиса выдает ошибку, что делать?

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

    Успешность обычно проверяют по http-коду ответа.

    Если же сервис сделан так, что код ответа всегда 200, то единственный верный способ будет пытаться анмаршалить оба и смотреть на поля, всё верно.
    Ответ написан
    1 комментарий
  • Почему int при делении int на int с остатком?

    Это не деление с остатком, это целочисленное деление.
    Если делишь одно целое число на другое целое число, работает целочисленная арифметика, потому что го это строго статически типизированный язык.
    Чтобы получить дробное число, нужно явно делить одно число с плавающей точкой на другое.
    package main
    
    import "fmt"
    
    func main() {
    	var some = float64(5) / float64(3)
    	fmt.Println(some)
    	fmt.Printf("%T", some)
    }


    Происходит это потому что компьютер так работает на уровне железа. Если процессору дать команду на деление двух целых, ответом будет целое. Если дать команду на деление двух флоатов — будет флоат.
    В некоторых языках компилятор или интерпретатор берут на себя смелость решать за пользователя, какой ему тип нужен и автоматически включают нужный тип деления в зависимости от ситуации (обычно включается флоат на флоат, как в JS, например). Но это может приводить к ошибкам в некоторых ситуациях.
    Поэтому в го, C, C++ и еще многих других языках (обычно это статически типизированные языки), пользователь должен явно выбирать требуемый тип деления, используя нужные типы переменных.
    Ответ написан
    1 комментарий
  • Go. Что делать, если в коде много схожих друг с другом функций?

    Наоборот, написать общую функцию для таких целей — это хороший способ.
    У вас тут посыл запроса, обработка кода ответа, парсинг. Это всё отлично выносится в общую функцию, которой потом удобно будет пользоваться. Особенно с дженериками, которые добавили в go1.18
    Ответ написан
    2 комментария
  • Как в Golang проверить вхождение строки в строку, но слово целиком?

    Такое делается предварительной токенизацией и потом поиском по токенам.
    Например так:
    https://go.dev/play/p/p5-eLLx1ilr

    С помощью регулярки указываем, какие символы не могут быть внутри слова (\s означает все пробельные символы, а дальше идёт перечисление знаков препинания).
    Потом делаем Split по регулярке, получаем набор токенов (слов), кладём их в мапу для быстрого поиска (можно оставить в массиве, если искать слово надо один раз).

    Если нужна возможность искать фразы (а они содержат пробелы), то индекс уже по-другому придется строить, самый простой способ — после токенизации сделать strings.Join(str, " "), тогда разделитель будет строго пробел на выходе.

    package main
    
    import (
    	"fmt"
    	"regexp"
    )
    
    func main() {
    	tokens := tokenize("something, something1, othersomething")
    
    	fmt.Println(tokens)
    
    	fmt.Println("some", tokens.containsWord("some"))
    	fmt.Println("thing", tokens.containsWord("thing"))
    	fmt.Println("something", tokens.containsWord("something"))
    }
    
    var re = regexp.MustCompile(`[\s,.;"']+`)
    
    type TokenizedString map[string]struct{}
    
    func tokenize(str string) TokenizedString {
    	list := re.Split(str, -1)
    	tokens := make(map[string]struct{}, len(list))
    	for _, token := range list {
    		tokens[token] = struct{}{}
    	}
    	return tokens
    }
    
    func (t TokenizedString) containsWord(word string) bool {
    	_, ok := t[word]
    	return ok
    }
    Ответ написан
    Комментировать
  • Почему не работает отладка для Go в VS Code?

    Судя по тексту ошибки, у вас нет корректного go.mod в корне проекта. Создайте его командой go mod init somename вместо somename принято ставить путь к репозиторию вашего проекта, но можно и просто имя.
    Ответ написан
    4 комментария
  • Как нормально "слепить" это?

    У автора на низкополигональный объект наложен модификатор subdivision surface, поэтому он может двигать большие полигоны на низкополигональной модельке и у него будет плавно деформироваться высокополигональная геометрия, которую создаёт subdivision surface.
    Судя по вашей картинке, вы применили (apply) модификатор и работаете с уже высокополигональной сеткой. Не нужно применять модификатор, работайте с низкополигональной сеткой.
    Ответ написан
    2 комментария
  • Как правильно обрабатывать ошибки в go?

    Пример, конечно, очень странный. Не ясно, где применять такую функцию.
    Но матчинг ошибки через Is и вынесение ее в var сделаны правильно.

    Is используем, когда надо проверить, наследована ли ошибка от указанной кастомной ошибки.

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

    https://go.dev/play/p/AGbxpqQKteC
    type CustomError struct {
    	Text     string
    	HttpCode int
    }
    
    func (c *CustomError) Error() string {
    	return c.Text
    }
    
    func main() {
    	err := doSomeStuff()
    	if err != nil {
    		customErr := &CustomError{}
    		if errors.As(err, &customErr) {
    			fmt.Println(customErr.Text, " http code:", customErr.HttpCode)
    		}
    	}
    }
    
    func doSomeStuff() error {
    	return &CustomError{
    		Text:     "please provide a password",
    		HttpCode: 401,
    	}
    }
    Ответ написан
    4 комментария
  • Как добавить запись в JSON файл?

    Вы правильно открываете файл, а потом используете WriteFile, вместо того, чтобы писать в открытый дескриптор файла.
    Правильно будет так:
    func WriteJson(d structs.Bassketball) error {
    	f, err := os.OpenFile("basketball.json", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
    	if err != nil {
    		return err
    	}
    	defer f.Close()
    
    	rawJSON, _ := json.Marshal(d)
    	_, err = f.Write(rawJSON)
    	if err != nil {
    		return err
    	}
    
    	return nil
    }
    Ответ написан
    1 комментарий
  • Какую 3D программу выбрать для изучения для моделирования нетривиальных предметов личного потребления?

    Blender, правда, на него сложно будет после Макса переходить, ибо флоу работы сильно отличается (по себе знаю, я именно так переходил).
    Там и простой моделинг есть и скульпт есть и процедурная геометрия на нодах. При этом бесплатный, легковесный и стабильнее, чем Макс.
    Ответ написан
    8 комментариев