Задать вопрос
  • Как синхронизировать горутины?

    EvgenyMamonov
    @EvgenyMamonov Куратор тега Go
    Senior software developer, system architect
    Горутины синхронизировать/обмениваться данными можно при помощи каналов.
    У вас не очень удачный пример для обучения.
    Обычно есть горутина или несколько, которые получают данные и пишут их в канал и есть горутина или несколько, которые будут читать из канала.
    Читающие горутины будут получать данные из канала в той последовательности, в которой они туда попали.
    Ближе к реальности пример будет выглядеть вот так.
    Одна горутина пишет данные в канал, а две горутины по очереди извлекают данные.
    package main
    
    import (
        "fmt"
        "sync"
        "time"
    )
    
    func main() {
        var wg sync.WaitGroup
    
        num := make(chan int, 1000) // 1000 - размер буффера канала
    
        wg.Add(1)
        go func() {
            for i := 0; i < 1000; i++ {
                num <- i
                fmt.Printf("write to channel: %d\n", i)
                // задержка нужна только на время теста
                time.Sleep(100 * time.Microsecond)
            }
            close(num)
            wg.Done()
        }()
    
        wg.Add(1)
        go func() {
            for {
                val, ok := <-num
                if !ok {
                    break
                }
                fmt.Printf("goroutine 1 got: %d\n", val)
            }
            wg.Done()
        }()
    
        wg.Add(1)
        go func() {
            for {
                val, ok := <-num
                if !ok {
                    break
                }
                fmt.Printf("goroutine 2 got: %d\n", val)
            }
            wg.Done()
        }()
    
        wg.Wait()
    }
    Ответ написан
    7 комментариев
  • Как дождаться загрузки JS на странице?

    udjin123
    @udjin123
    PHP, Golang, React
    golang не выполняет ни какой код получаемый из запроса, для него это тупо срез байтов, вся обработка ложиться на вас. По этому или chromedriver с помощью agouti или какие-нибудь экзотические библиотеки типа v8go

    Но лучше конкретизировать вопрос и написать какую задачу пытаетесь решить, вероятнее всего вам вообще не нужно взаимодействовать с js
    Ответ написан
    3 комментария
  • Работа с goroutines?

    EvgenyMamonov
    @EvgenyMamonov Куратор тега Go
    Senior software developer, system architect
    Есть несколько вариантов решения задачи
    передавать не указатель, а значение

    package main
    
    import (
      "fmt"
      "time"
    )
    
    var c = make(chan int, 3)
    var data = []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
    
    func main() {
      fmt.Println("Hello, playground")
      go save()
      go read()
      time.Sleep(3 * time.Second)
    }
    
    func save() {
      for _, val := range data {
        c <- val
      }
    }
    
    func read() {
      for {
        val := <-c
        fmt.Println("read:", val)
      }
    }

    скопировать значение и передать указатель на это значение

    package main
    
    import (
    	"fmt"
    	"time"
    )
    
    var c = make(chan *int)
    var data = []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
    
    func main() {
    	fmt.Println("Hello, playground")
    	go save()
    	go read()
    	time.Sleep(3 * time.Second)
    }
    
    func save() {
    	for _, val := range data {
    	        v := val
    		c <- &v
    	}
    }
    
    func read() {
    	for {
    		val := <-c
    		fmt.Println("read:", *val)
    	}
    }

    передать правильный указатель, на элемент данных

    package main
    
    import (
    	"fmt"
    	"time"
    
    
    var c = make(chan *int, 5)
    var data = []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
    
    func main() {
    	fmt.Println("Hello, playground")
    	go save()
    	go read()
    	time.Sleep(3 * time.Second)
    }
    
    func save() {
    	for i := range data {
    		c <- &data[i]
    	}
    }
    
    func read() {
    	for {
    		val := <-c
    		fmt.Println("read:", *val)
    	}
    }



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

    Вот пример, который покажет, что адрес всегда один и тот же
    package main
    
    import (
    	"fmt"
    	"time"
    )
    
    var c = make(chan *int, 5)
    var data = []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
    
    func main() {
    	fmt.Println("Hello, playground")
    	go save()
    	go read()
    	time.Sleep(3 * time.Second)
    }
    
    func save() {
    	for _, val := range data {
    		c <- &val
    		fmt.Printf("write: %v\n", &val)
    	}
    }
    
    func read() {
    	for {
    		val := <-c
    		fmt.Println("read:", *val)
    	}
    }

    Вывод будет таким (адрес один и тот же)
    Hello, playground
    write: 0xc000094000
    write: 0xc000094000
    write: 0xc000094000
    write: 0xc000094000
    write: 0xc000094000
    write: 0xc000094000
    ...


    А в такой реализации (2й пример)
    func save() {
    	for _, val := range data {
    		v := val
    		c <- &v
    		fmt.Printf("write: %v\n", &v)
    	}
    }

    тут вывод будет таким (каждый раз новый участок памяти)
    Hello, playground
    write: 0xc000094000
    write: 0xc000094010
    write: 0xc000094018
    write: 0xc000094020
    write: 0xc000094028
    write: 0xc000094030

    В третьем варианте тоже будут разные указатели.
    Ответ написан
    5 комментариев
  • Текущее положение Golang в машинном обучение?

    sgjurano
    @sgjurano
    Разработчик
    Можно запускать либы, написанные на C из Go, но зачем?

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

    Пожалуй единственная нормальная причина использовать ML-библиотеки на Go — это когда у вас уже есть сервис на Go, к которому надо прикрутить немножко ML.

    Если же вы пишете новый сервис, где планируется активное использование ML-библиотек, то для невысокой нагрузки прекрасно подойдёт Python, а для высокой лучше всё же сразу взять C++ или какой-нибудь другой язык прозрачно совместимый по памяти с C.

    Поэтому мне кажется, что ML-библиотеки на Go так и будут капитально отставать от Python — они там просто почти никому не нужны, вот их и не развивают.
    Ответ написан
    4 комментария
  • Не будет гонки и повреждения данных в памяти?

    @falconandy
    По-моему вы переусложняете без необходимости. Если значения из конфига только читаются, то потокобезопасность не нужна. Если же у вас предполагается еще и изменение, то в пул возвращаются указатели на "порченные" объекты, что тоже неправильно.
    Если возможно, конфиг лучше прочитать в начале выполнения, а также паниковать на уровне main.
    В результате и код проще, и тормозить нечему:
    package config
    
    import (
    	"encoding/json"
    	"fmt"
    	"os"
    )
    
    type Cfg struct {
    	// Fields
    }
    
    var (
    	cfg *Cfg
    )
    
    func Config() *Cfg {
    	return cfg
    }
    
    func LoadConfig() error {
    	f, err := os.Open("./config/config.json")
    	if err != nil {
    		return fmt.Errorf("can't open config file: %w", err)
    	}
    	defer f.Close()
    
    	dec := json.NewDecoder(f)
    	var c *Cfg
    	if err := dec.Decode(c); err != nil {
    		return fmt.Errorf("can't decode config file: %w", err)
    	}
    
    	if err := validate(c); err != nil {
    		return fmt.Errorf("can't validate config file: %w", err)
    	}
    	
    	cfg = c
    
    	return nil
    }
    
    func validate(cfg *Cfg) error {
    	// Logic
    	return nil
    }
    Ответ написан
    Комментировать
  • Насколько пригодна программа Shapr3D для профессионалов?

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

    EvgenyMamonov
    @EvgenyMamonov Куратор тега Go
    Senior software developer, system architect
    Потому, что 65 - это код английской буквы "A".

    Если вы хотите чтобы отобразило 65, нужно использовать либо модуль strconv, либо fmt.
    package main
    
    import "fmt"
    import "strconv"
    
    func main() {
      var i int64 = 65
      fmt.Println(strconv.FormatInt(i, 10))
      // или так
      fmt.Printf("%d\n", i)
    }
    Ответ написан
    2 комментария
  • Где можно использовать горутины в Go?

    EvgenyMamonov
    @EvgenyMamonov Куратор тега Go
    Senior software developer, system architect
    Самый простой пример - это HTTP сервер.
    Когда к вам приходит HTTP запрос - создаётся горутина и каждый запрос спокойно обрабатывается, никто никого не ждёт. Т.е. сервер может обрабатывать параллельно несколько запросов как раз за счёт горутин.

    Фактически, почти во всех сетевых сервисах есть смысл использовать горутины для распараллеливания обработки запросов (кроме epoll, kqueue и т.п.)

    Еще хороший пример.
    Вам нужно сделать парсер Авито :)) или индесатор сайтов.
    Т.е. задача сводится к тому, что нужно будет постоянно качать страницы с сайтов.
    Если вы будете качать одну страницу за другой - вы будете очень долго качать.
    А так вы можете сделать пул из нескольких горутин (как минимум по 1 на поток процессора) и получите параллельное скачивание страниц.

    Для ускорения работы вычислений (параллельные вычисления) есть смысл использовать горутины только по 1 на поток процессора). Т.е. в случаях, когда у вас огромный объём данных и нужно максимально ускорить его обработку. Например у вас файл 100Гб, и 8 ядер в процессоре - вы можете разбить файл на 8 частей и параллельно эти части обработать (в самом простом варианте, в реальной жизни нужно будет просто по частям считывать новые данные и скармливать свободной горутине)

    Еще когда нужно сделать чтобы какая нибудь задача выполнялась в "фоне".
    Например периодическая очистка кеша/устаревший записей в базе.

    Реальных примеров намного больше :)
    В целом их есть смысл использовать там, где нужно параллельное выполнение какой либо задачи или разных задач параллельно :)
    Ответ написан
    2 комментария
  • Какую книгу выбрать для изучения компьютерной графики?

    Один из самых лучших ресурсов по комп. графике: https://www.scratchapixel.com/

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

    @12rbah
    Другие ребята советую сразу начинать с С++,
    Если плохо знаете язык, то да стоит его подучить.
    издание Столярова
    Я честно скажу не читал его, но по оглавлению похоже на упрощенный курс по программированию сетям и ОС, возможно есть смысл читать как доп. литературу, если не разбираетесь в теме.

    Думаю вам есть смысл изучить сначала c++ хотя бы на уровне учебника праты, липмана, а потом думаю имеет смысл совместно изучать комп. графику и с++ (паттерны, stl, стандарты и тд). Можете попробовать изучать комп. графики и c++ сразу, может потянете.

    Ссылки на источники для изучения (вы не указали конкретного направления, так что выбирайте, что понравится):
    неплохое видео https://www.youtube.com/watch?v=Q9zkiOClyEo
    тема на редите (в теме есть несколько ссылок) https://www.reddit.com/r/GraphicsProgramming/comme...
    книга Компьютерная графика в среде MS VS C++ (2017)
    хабр https://habr.com/ru/post/248153/
    Ответ написан
    2 комментария
  • Что нужно писать в файлах proto в option go_package?

    @ghostiam
    На Go писатель, серверов пинатель.
    Нужно указать полный путь до пакета, где будут лежать сгенерированные файлы.
    В вашем случае (если будете держать сгенерированные и прото файлы в /protos/fizz)
    option go_package = "example.com/project/protos/fizz";

    далее запускаете генерацию с опцией
    --go_opt=paths=source_relative

    If the paths=source_relative flag is specified, the output file is placed in the same relative directory as the input file. For example, an input file protos/buzz.proto results in an output file at protos/buzz.pb.go.

    https://developers.google.com/protocol-buffers/doc...

    Загружать код в репозиторий не нужно.
    Ответ написан
    4 комментария
  • Не определены стандартные пакеты Golang?

    WinPooh32
    @WinPooh32
    Stack Overflow answer searching expert
    Никогда не устанавливайте программы вручную в корень системы, как в вашей инструкции. Почти всегда есть готовые пакеты. Лучше уже через докер ставить, лезть в систему - крайний случай.
    (и советую все вернуть как было до ручной установки)

    Го лучше поставить через snap (а вот vscode лучше через deb с сайта):
    sudo snap install go --channel=1.16/stable --classic


    Когда понадобятся другие версии, VScode может сам установить в папку желаемую версию и будет использовать её:
    ctrl+shift+p, вводите Go: Locate Configured Go Tools (или на панели снизу можно найти кнопку).

    Бывает что анализатор может заглючить и перезапуск gopls помогает: ctrl+shift+p, Go: Restart language Server

    И убедитесь, что го расширение установлено в редактор.
    Ответ написан
    Комментировать
  • Как применить множество фильтров на входящий поток?

    uvelichitel
    @uvelichitel Куратор тега Go
    habrahabr.ru/users/uvelichitel
    Еще например вот так можно
    type FReader struct {
    	reader io.Reader
    	filter func([]byte) (int, error)
    }
    func NewFReader(r io.Reader) *FReader {
    	return &FReader{r, func(p []byte) (int, error) { return len(p), nil }}
    }
    func (fr *FReader) Filter(filter func([]byte) (int, error)) *FReader {
    	return &FReader{fr, filter}
    }
    func (fr *FReader) Read(p []byte) (n int, err error) {
    	n, err = fr.reader.Read(p)
    	if err == nil && fr.filter != nil {
    		n, err = fr.filter(p)
    	}
    	return
    }

    тогда можно написать
    chainreader := NewFReader(myreader).Filter(myfilter1).Filter(myfilter2).Filter(myfilter3)
    https://play.golang.org/p/rakSV5kgqR9
    Ответ написан
    1 комментарий
  • Как обработать данные в горутинах пакетами?

    Stasgar
    @Stasgar
    Обученная макака
    Есть паттерн Worker Pool, пример можете посмотреть здесь: https://gobyexample.com/worker-pools
    Ответ написан
    5 комментариев
  • Горутино-безопасное обоащение к sqlite3?

    uvelichitel
    @uvelichitel Куратор тега Go
    habrahabr.ru/users/uvelichitel
    Если вы работаете с sql консистентность данных гарантируется и обеспечивается движком базы через механизм транзакций. Транзакции отражены в пакете database/sql из стандартной библиотеки https://golang.org/pkg/database/sql/#Tx Ничего особенного на уровне языка делать вообще нет необходимости, просто не обращайтесь к одной транзакции из нескольких горутин.
    Ответ написан
    6 комментариев
  • Golang. Самописный пакет не видим из основного модуля?

    2ord
    @2ord
    Или возьмите старую версию Go, как у "ютуберов", или же, наконец, начните использовать go modules.
    Ответ написан
    2 комментария
  • Можно ли в Go собрать проект с объявленными, но не используемыми переменными?

    @ghostiam
    На Go писатель, серверов пинатель.
    Нет, собрать нельзя.
    Можно сделать финт ушами(но это дурной тон)
    var _ = fmt.Println
    var _ = myvar

    То есть, воспользоваться нужно в любом случае.

    На самом деле, это очень хорошая фишка, делает код чистым(у меня во всех других языках всегда включён такой же линтер), а с импортами при комментировании проблем никаких не возникает, если пользоваться IDE.
    Ответ написан
    5 комментариев
  • Почему не видна функция определённая в другом файле, но в том же пакете?

    EvgenyMamonov
    @EvgenyMamonov Куратор тега Go
    Senior software developer, system architect
    Суть проблемы в том, что вы указываете только файл с тестом, а нужно указать еще и файл с декларацией и реализацией (если они разные).

    Вот так будет работать:
    go test -v ./driver_test.go ./driver.go

    Подозреваю, что реально вы хотели сделать чтобы у вас выполнялись не все тесты в пакете, а конкретный один, если так - тогда проще делать вот так (я сам так часто делаю :)))
    go test -v -run ^Test_Deposit$
    Ответ написан
    Комментировать
  • Чем запуск горутины отличается от запуска функции?

    @ghostiam
    На Go писатель, серверов пинатель.
    Потому-что горутина запускается в новом "потоке" приложения и главный поток не блокируется.
    Чтобы дождаться завершения работы всех горутин, нужно использовать sync.WaitGroup
    https://gobyexample.com/waitgroups
    https://golang.org/pkg/sync/#example_WaitGroup
    Ответ написан
    Комментировать
  • Как можно конвертировать изображение (jpg, png) в pdf?

    Adamos
    @Adamos
    ImageMagick делает все, что нужно вам, и очень много всего, что вам никогда не понадобится. Нужно просто один раз с ним разобраться.
    Ответ написан
    Комментировать