Задать вопрос
  • Какую технологию выбрать для live трансляции go?

    Проще всего взять за основу ffmpeg, он очень гибкий есть куча примеров, как на его основе делать трансляции через протокол HLS.

    Go тут по сути будет использоваться как оркестратор для запуска ffmpeg и предоставления доступа к hls-кускам видео и плейлистам.

    В свое время ковырял эту связку, в целом так программу для трансляций можно собрать за день.
    Ответ написан
    2 комментария
  • Какая есть бесплатная программа для 3D с поддержкой скриптов?

    Есть бесплатный Blender, в котором можно писать скрипты на Питоне и плагины тоже на нем.

    Плюс, там есть геоноды, с помощью которых можно визуальным программмированием делать процедурное моделирование.
    Ответ написан
    4 комментария
  • Отправка загруженной фото в боте -> пользователю?

    Есть минимум два способа
    1. Выгрузить фото в файл или s3 и дать на него урл
    2. Выгрузить фото в качестве сырых данных в файл или в память и отправить эти данные другому пользователю через sendPhoto


    Если правильно помню, просто переслать файл-айди не получится, потому что у Телеги файл-айди разный для разных пользователей и ботов.
    Ответ написан
    Комментировать
  • Как использовать GOOS в exec.Command?

    Способ из инета костыльный, по-хорошему нужно делать так:

    cmd := exec.Command("go", "build", ".")
    cmd.Env = os.Environ()
    cmd.Env = append(cmd.Env, "GOOS=windows")
    Ответ написан
    3 комментария
  • С помощью какой библиотеки или бесплатного api можно конвертировать 3d модели в разные форматы?

    Blender

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

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

    Должен подойти такой вариант
    func start() {
    	file, _ := os.ReadFile("./data.txt")
    
    	for _, i := range strings.Split(string(file), "\n") {
    		select {
    		case <-stop:
    			return
    		default:
    			http.Get(Url + i)
    		}
    	}
    }


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

    Более сложный вариант

    package main
    
    import (
    	"context"
    	"errors"
    	"io/ioutil"
    	"net/http"
    	"strings"
    )
    
    func start() {
    	file, _ := os.ReadFile("./data.txt")
    
    	ctx, cancel := context.WithCancel(context.Background())
    	defer cancel() // контекст обязательно надо отменять в конце
    
    	go func() {
    		select {
    
    		// Отменяем контекст при получении стоп-сигнала
    		case <-stop:
    			cancel()
    
    		// чтобы горутина завершилась по отмене контекста даже если stop не будет
    		case <-ctx.Done():
    		}
    	}()
    
    	for _, i := range strings.Split(string(file), "\n") {
    		err := processUrl(ctx, Url+i)
    		if err != nil {
    			if errors.Is(err, context.Canceled) {
    				return
    			}
    			// обработать ошибку
    		}
    	}
    }
    
    func processUrl(ctx context.Context, finalUrl string) error {
    	req, err := http.NewRequestWithContext(ctx, "GET", finalUrl, nil)
    	if err != nil {
    		return err
    	}
    	res, err := http.DefaultClient.Do(req)
    	if err != nil {
    		return err
    	}
    	defer res.Body.Close() // обязательно, иначе будет утечка
    
    	// обработать ответ
    
    	return nil
    }



    Здесь уже выход будет мгновенный, потому что http-запрос отменится по контексту хоть на середине.
    Ответ написан
  • Почему Go не видит бинарники в GOBIN?

    Го сам никакие пути к бинарникам не ищет, он обращается за этим к операционной системе. Поэтому добавьте вашу папку с бинарниками в переменную окружения PATH вашей ОС.

    GOBIN определяет путь, куда Го будет билдить бинарники, которые устанавливаются через go install. Но он не отвечает за их поиск там.
    Ответ написан
    Комментировать
  • Как сделать плавное перетекание текстур в блендер?

    Самый простой способ это сделать такой шейдер
    63ce6c21eff31708991280.png

    Потом заанимировать параметр factor у ноды mix
    При factor=0 будет отображаться первая текстура, при factor=1 вторая. В промежуточных значениях текстуры будут плавно смешиваться

    Если нужно чтобы текстура натекала не по всему объекту сразу, а ближе к эффекту на видео, снизу вверх, например, то это уже сложнее. Нужно будет factor брать из третьей градиентной текстуры и анимировать её маппинг по объекту.
    Ответ написан
  • Как в GO написать свою функцию к другим типам?

    Логично, что ругается. Вы объявили метод у типа strType, а переменную создали типа string.

    Нужно делать так:
    package main
    
    func main() {
    	var str strType
    
    	str.Temp()
    }
    
    type strType string
    
    func (s strType) Temp() {
    }
    Ответ написан
    3 комментария
  • Для чего в go.mod добовить зависимости если мы указываем полный путь к ним в коде?

    Для указания версий этих зависимостей. Чтобы бралась не последняя версия, а указанная. Обеспечивает повторяемость релизов и стабильность.
    Ответ написан
    Комментировать
  • Почему env GOPATH больше не имеет значения?

    Раньше все зависимости лежали в GOPATH, но это было неудобно тем, что не было никакого управления этими зависимостями. Нельзя было зафиксировать их конкретные версии и нельзя было для разных проектов сделать разные зависимости, потому что все было в одной центральной папке.
    Потом в го ввели систему модулей:
    https://go.dev/blog/using-go-modules
    https://habr.com/ru/company/otus/blog/503918/

    Теперь в корневой папке каждого проекта есть файл go.mod, который перечисляет зависимости этого проекта и их конкретные версии. Поэтому необходимость в GOPATH отпала, теперь Go при сборке использует модули, указанные в go.mod и не ходит в GOPATH вообще, это намного удобнее.
    Ответ написан
    4 комментария
  • Как зашифровать http запрос?

    Использовать https, тогда можно будет зашифровать в том числе урл.
    Если делать свое шифрование поверх http, то во-первых, это будет сильно сложнее сделать правильно и надежно, во-вторых, не получится зашифровать урл, потому что по стандарту http он должен быть в открытом виде.
    Ответ написан
    Комментировать
  • Подс-жите программу для фоновой 3D-нагрузки видеокарты?

    Это видеокарта экономит энергию, называется опция power mizer, ее можно найти в панели управления нвидия и включить всегда на performance.
    Ответ написан
  • Как понять от первого элемента в слайсе(capacity)?

    Каждый раз, когда у слайса кончается капасити, го делает переаллокацию данных в памяти, увеличивая капасити и копируя старые данные в новую аллоцированную область. Причем, капасити растет с запасом, чтобы свести количество переаллокаций к минимуму (ибо это дорогая операция). Поэтому это нормальная ситуация, когда капасити становится больше, чем длина. Го вам делает запас на будущее.
    Ответ написан
    2 комментария
  • Какой программой можно получить изображения как у компании 3dfab.ru?

    В любом современном рендерере. Из бесплатных, например, Blender+cycles.
    Ответ написан
    Комментировать
  • Как реализовать такое облако слов?

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

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

    Лучше сделать так
    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 используется для того, чтобы подождать, пока воркеры доработают последние данные.
    Ответ написан
    Комментировать
  • Как в процессе выполнения программы считывать вывод?

    Все гораздо проще. Вы можете сразу в 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 комментария
  • Как понять каррирование и частичное применение функции? В чём их различия?

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

    Что вообще происходит в теле возвращаемой функции?

    Так немного некорректно рассуждать, потому что компилятор может по-разному оптимизировать внутренность функции.

    Но если вам будет проще понять, можно представить, что у нас не Хаскель, а обычный императивный язык. Тогда частичное применение можно эмулировать с помощью замыкания:
    func main() {
    	fmt.Println(sum(1, 2))
    
    	carried := carry(sum, 1)
    	fmt.Println(carried(2))
    }
    
    func sum(a, b int) int {
    	return a + b
    }
    
    func carry(fn func(int, int) int, a int) func(int) int {
    	return func(b int) int {
    		return fn(a, b)
    	}
    }

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

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

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