Задать вопрос
  • Как устранить утечку памяти при множественных соединениях в net/http Golang?

    EvgenyMamonov
    @EvgenyMamonov Куратор тега Go
    > Данный код приводит к огромной утечке памяти

    Хорошо бы, для начала понять, сколько памяти реально течёт, есть сомнения, что эта map'а, занимает много памяти.

    > Эта функция запускается сразу в большом кол-ве горутин (go scan())

    Также нужно понять сколько горутин запускается?
    Почему? Потому, что каждая из них, в зависимости от размера стэка, потребляет память.
    Если их запускается очень много и/или, например, они не завершаются, вот тут уже более реальна "огромная" утечка памяти.
    Написано
  • Структура проекта на Golang?

    EvgenyMamonov
    @EvgenyMamonov Куратор тега Go
    В этом плане лучше почитать книгу Роберта Мартина "Чистая архитектура".

    Если в двух словах то:

    Repository — отвечает за получение данных из внешних источников, такие как база данных и т.д., но в нём нет бизнес логики.

    Service — отвечает за бизнес логику, использует Repository для манипуляций с данными.
  • Нужен ли Nginx для веб приложения на Golang?

    EvgenyMamonov
    @EvgenyMamonov Куратор тега Go
    Лучше использовать nginx, т.к. рано или поздно вам понадобиться повесить более одного домена на IP и тогда вы опять столкнётесь с таким же выбором. Лучше сразу разобраться с Nginx, потом не раз еще пригодиться. В вашем случае я бы оставил go на 4000 порту, а 80 и 443 порты обрабатывал бы Nginx.

    Nginx определённо путь наименьшего сопротивления + его настройка будет определённо полезным навыком.
  • Новичёк без предыдущего опыта в разработке, способен устроиться сейчас Junior Golang Developer?

    Да да, с Java начинать будет явно сложнее/дольше, чем со скриптового языка.
  • Как отдать картинку в ответе веб сервиса в Gin framework?

    EvgenyMamonov
    @EvgenyMamonov Куратор тега Go
    Нужно больше подробностей.
    Напишите на какой URL вы отправляете запрос в броузере и в Postman.
    Какой запрос делаете в Postman, какой ответ получаете.
    Возможно запрос не туда уходит или URL не правильно обрабатывается, в общем опишите максимально подробно, так очень трудно сказать.
  • Зачем нужны интерфейсы в go?

    EvgenyMamonov
    @EvgenyMamonov Куратор тега Go
    Мне других вариантов не встречалось )
  • Как сделать автоматическое заполнение форм на сайте через скрипт Golang?

    EvgenyMamonov
    @EvgenyMamonov Куратор тега Go
    Смотрели какие данные отправляет браузер если отправить запрос с него?
    Посмотрите какие данные, какие заголовки браузер отправляет, надо делать 1в1.

    user_forms[0][surname] - это точно название поля в форме, т.е. в исходнике страницы оно выглядит как <input name="user_forms[0][surname]" .. /> ?

    "а желаемый результат не очень" тут нужны подробности, что конкретно приходит в ответ и что должно приходить?
  • LDAP with Golang (создать сервер) как?

    EvgenyMamonov
    @EvgenyMamonov Куратор тега Go
    ну и очень странно выглядят всё теже строки

    // тут вы запускаете http сервер
    http.ListenAndServe(":389", nil)

    // а тут вы к нему же подключаетесь
    l, err := ldap.DialURL("ldap://localhost:389")

    как по мне это выглядит странновато :)
  • LDAP with Golang (создать сервер) как?

    EvgenyMamonov
    @EvgenyMamonov Куратор тега Go
    Что именно не работает?
    Судя по коду - он должен зависать на строке http.ListenAndServe(":389", nil), надо её запустить как горутину.
  • Выполнение/вызов функции из Go файла при нажатии на кнопку html?

    EvgenyMamonov
    @EvgenyMamonov Куратор тега Go
    Furylon, вот... видите, еще не успели начать писать, а проблемы из-за глобальных переменных уже начались ))
  • Выполнение/вызов функции из Go файла при нажатии на кнопку html?

    EvgenyMamonov
    @EvgenyMamonov Куратор тега Go
    Вот проверенный вариант, возьмите его за основу и в него уже добавляйте ваш код
    package main
    
    import (
      "database/sql"
      "fmt"
      "html/template"
      _ "github.com/go-sql-driver/mysql"
      "github.com/gorilla/mux"
      "math/rand"
      "net/http"
      "time"
    )
    
    type WordsStruct struct { // выгрузка БД
      Id    int
      Fword string
      Sword string
      Freq  int
    }
    
    var database *sql.DB
    
    // глобальные переменные - это плохо, с ними будет трудно работать в будущем,
    // особенно при покрытии кода тестами
    // но сейчас мы её используем, чтобы не усложнять код.
    var words []WordsStruct
    
    var err error
    
    // LoadWords вычитывает все данные из таблицы words
    func LoadWords() ([]WordsStruct, error) {
        res, err := database.Query(fmt.Sprintf("SELECT * FROM `words`"))
        if err != nil {
            return nil, err
        }
        defer res.Close()
    
        wordsarray := []WordsStruct{}
    
        for res.Next() {
            var sw WordsStruct
            err := res.Scan(&sw.Id, &sw.Fword, &sw.Sword, &sw.Freq)
            if err != nil {
          fmt.Println(err)
          continue
            }
            wordsarray = append(wordsarray, sw)
        }
        return wordsarray, nil
    }
    
    func MainPage(w http.ResponseWriter, r *http.Request) {
        m, _ := template.ParseFiles("html/main.html", "html/header.html", "html/footer.html")
    
        // берём данные из глобальной переменной words, 
        // которая уже хранит вычитанные данные из базы
        show := Next(words)
    
        m.ExecuteTemplate(w, "main", show)
    }
    
    
    func Next(st []WordsStruct) WordsStruct {
        shw := st[rand.Intn(len(st))]
        return shw
    }
    
    func List(w http.ResponseWriter, r *http.Request) {
        m, _ := template.ParseFiles("html/list.html", "html/header.html", "html/footer.html")
    
        // берём данные из глобальной переменной words, 
        // которая уже хранит вычитанные данные из базы
        m.ExecuteTemplate(w, "list", words)
    }
    
    func AddWords(w http.ResponseWriter, r *http.Request) {
        // тут вы пишите новое слово в базу
    
        // после записи в базу нужно будет перечитать данные заново (простой вариант)
        // или модифицировать структуру (правильный вариант, т.к. снижает нагрузку на базу)
        // пойдём простым путём
        words, err = LoadWords()
        if err != nil {
            // ответ об ошибке
            return
        }
    
        // ответ когда все хорошо
    }
    
    // *****************************************************************************************************************************************************************
    
    func StartFunc() {
        rtr := mux.NewRouter()
    
        http.Handle("/", rtr)
    
        http.Handle("/css/", http.StripPrefix("/css/", http.FileServer(http.Dir("./css/"))))
        http.Handle("/js/", http.StripPrefix("/js/", http.FileServer(http.Dir("./js/"))))
        http.Handle("/html/", http.StripPrefix("/html/", http.FileServer(http.Dir("./html/"))))
    
        rtr.HandleFunc("/", MainPage)
        rtr.HandleFunc("/list", List)
        rtr.HandleFunc("/addwords", AddWords).Methods("POST")
    
        http.ListenAndServe(":5500", nil)
    }
    
    func main() {
        // лучше вызывать rand.Seed один раз при запуске, а не каждый раз, 
        // иначе можно будет просчитать результат.
        rand.Seed(time.Now().Unix())
    
        db, err := sql.Open("mysql", "root:@tcp(127.0.0.1:3306)/wordcard")
        if err != nil {
            //log.Println(err)
            panic(err)
        }
    
        database = db
        defer db.Close()
    
        // вычитываем данные из базы и сохраняем их в структуру, 
        // чтобы потом могли их использовать в ответе	
        words, err = LoadWords()
        if err != nil {
            panic(err)
        }
        StartFunc()
    }
  • Выполнение/вызов функции из Go файла при нажатии на кнопку html?

    EvgenyMamonov
    @EvgenyMamonov Куратор тега Go
    Подозреваю, что ругается на то, что err не объявлен, объявите его.
    Я код написал руками, без IDE, мог подобные вещи упустить :)
    func main () {
        var err error // объявите err
        words, err = LoadWords()
        if err != nil {
            panic(err)
        }
    }
  • Выполнение/вызов функции из Go файла при нажатии на кнопку html?

    EvgenyMamonov
    @EvgenyMamonov Куратор тега Go
    Вам просто нужно идти последовательно, вы взяли задачу, для реализации которой нужно освоить сразу много разных направлений, такое одномоментно трудно "переварить".

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

    Если будет нужна помощь с придумыванием задач :) - пишите, постараюсь вам помочь.
  • Как работает данный код?

    EvgenyMamonov
    @EvgenyMamonov Куратор тега Go
    Скорее все инициализировать этот код нужно будет как то так
    s := Server{servers: []*HTTPServer{}}
    
    // После чего нужно добавить "слушателей".
    l := net.Listen("tcp", ":3001")
    s.Accept(":3001", l)
    // после чего вызывать
    s.serveAPI()


    Подозреваю что задача того, кто писал этот код была в том, чтобы запускать сервера на разных IP, портах.
    Если задача стоит такая - то вот простой и понятный вариант
    package main
    
    import (
        "net/http"
        "fmt"
        "log"
    )
    
    func main() {
    
        handler := http.NewServeMux()
        handler.HandleFunc("/", handlerFunc)
    
        // первый сервер
        go func() {
            http.ListenAndServe("localhost:3001", handler)
        }()
    
        // второй сервер
        go func() {
            http.ListenAndServe("localhost:3001", handler)
        }()
    
        // последний сервер
        http.ListenAndServe("localhost:3002", handler)
    }
    
    func handlerFunc(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Got new request")
    }
  • Выполнение/вызов функции из Go файла при нажатии на кнопку html?

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

    Ваш main.go должен быть примерно таким
    package main
    
    import (
    	"database/sql"
    	"fmt"
    	"html/template"
    	//"log"
    	_ "github.com/go-sql-driver/mysql"
    	"github.com/gorilla/mux"
    	"math/rand"
    	"net/http"
    	"time"
    )
    
    type WordsStruct struct { // выгрузка БД
    	Id    int
    	Fword string
    	Sword string
    	Freq  int
    }
    
    var database *sql.DB
    
    // глобальные переменные - это плохо, с ними будет трудно работать в будущем,
    // особенно при покрытии кода тестами
    // но сейчас мы её используем, чтобы не усложнять код.
    var words []WordsStruct
    
    // LoadWords вычитывает все данные из таблицы words
    func LoadWords() ([]WordsStruct, error) {
        res, err := database.Query(fmt.Sprintf("SELECT * FROM `words`"))
        if err != nil {
            return nil, err
        }
        defer res.Close()
    
        wordsarray := []WordsStruct{}
    
        for res.Next() {
            var sw WordsStruct
            err := res.Scan(&sw.Id, &sw.Fword, &sw.Sword, &sw.Freq)
            if err != nil {
    	    fmt.Println(err)
    	    continue
            }
            wordsarray = append(wordsarray, sw)
        }
        return wordsarray, nil
    }
    
    func MainPage(w http.ResponseWriter, r *http.Request) {
        m, _ := template.ParseFiles("html/main.html", "html/header.html", "html/footer.html")
    
        // берём данные из глобальной переменной words, 
        // которая уже хранит вычитанные данные из базы
        show := Next(words)
    
        m.ExecuteTemplate(w, "main", show)
    }
    
    
    func Next(st []WordsStruct) WordsStruct {
        shw := st[rand.Intn(len(st))]
        return shw
    }
    
    func List(w http.ResponseWriter, r *http.Request) {
        m, _ := template.ParseFiles("html/list.html", "html/header.html", "html/footer.html")
    
        // берём данные из глобальной переменной words, 
        // которая уже хранит вычитанные данные из базы
        m.ExecuteTemplate(w, "list", words)
    }
    
    func AddWords(w http.ResponseWriter, r *http.Request) {
        // тут вы пишите новое слово в базу
    
        // после записи в базу нужно будет перечитать данные заново (простой вариант)
        // или модифицировать структуру (правильный вариант, т.к. снижает нагрузку на базу)
        // пойдём простым путём
        words, err = LoadWords()
        if err != nil {
            // ответ об ошибке
            return
        }
    
        // ответ когда все хорошо
    }
    
    // *****************************************************************************************************************************************************************
    
    func StartFunc() {
        rtr := mux.NewRouter()
    
        http.Handle("/", rtr)
    
        http.Handle("/css/", http.StripPrefix("/css/", http.FileServer(http.Dir("./css/"))))
        http.Handle("/js/", http.StripPrefix("/js/", http.FileServer(http.Dir("./js/"))))
        http.Handle("/html/", http.StripPrefix("/html/", http.FileServer(http.Dir("./html/"))))
    
        rtr.HandleFunc("/", MainPage)
        rtr.HandleFunc("/list", List)
        rtr.HandleFunc("/addwords", AddWords).Methods("POST")
    
        http.ListenAndServe(":5500", nil)
    }
    
    func main() {
        // лучше вызывать rand.Seed один раз при запуске, а не каждый раз, 
        // иначе можно будет просчитать результат.
        rand.Seed(time.Now().Unix())
    
        db, err := sql.Open("mysql", "root:@tcp(127.0.0.1:3306)/wordcard")
        if err != nil {
            //log.Println(err)
            panic(err)
        }
    
        database = db
        defer db.Close()
    
        // вычитываем данные из базы и сохраняем их в структуру, 
        // чтобы потом могли их использовать в ответе	
        words, err = LoadWords()
        if err != nil {
            panic(err)
        }
        StartFunc()
    }

    PS: вот так делать совсем нельзя, вы получите SQL инъекцию + Query используется для извлечения данных, для записи используйте Exec
    db.Query(fmt.Sprintf("INSERT INTO `words` (`firstword`, `secondword`, `freq`) VALUES ('%s', '%s', '%d')", firstWord, secondWord, frequens))

    Делайте лучше так
    db.Exec("INSERT INTO `words` (`firstword`, `secondword`, `freq`) VALUES (?, ?, ?)", firstWord, secondWord, frequens))


    Когда это у вас заработает, следующим шагом нужно проработать обмен данными в формате JSON.
  • Как работает данный код?

    EvgenyMamonov
    @EvgenyMamonov Куратор тега Go
    l - это интерфейс https://pkg.go.dev/net#Listener тут же есть и пример использования.
    Для чего вам нужно использовать именно этот код?
    Скорее всего будет лучше использовать для этого пакет net/http
  • Выполнение/вызов функции из Go файла при нажатии на кнопку html?

    EvgenyMamonov
    @EvgenyMamonov Куратор тега Go
    Rerurk, пока нет, но тоже интересно его попробовать :) Пока для мобильных приложений и т.д. используем Flutter.
  • Выполнение/вызов функции из Go файла при нажатии на кнопку html?

    EvgenyMamonov
    @EvgenyMamonov Куратор тега Go
    Furylon, опишите пожалуйста задачу которую вы решаете, так будет проще найти правильное решение задачи. Сейчас у вас описано ваше решение задачи, а не сама задача.

    Полностью согласен с Rerurk, в идеале вам нужно разобраться как именно происходит взаимодействие клиентского JavaScript с сервером.

    Возможно у вас не самая подходящая для обучения задача выбрана.
    Лучше начать с задачи попроще.

    Например...
    Получение времени сервера по нажатию кнопки.
    Т.е. вы в браузере нажали кнопку, на сервер ушел запрос типа "сколько сейчас времени", вернулся ответ 10:30 и вы отобразили этот ответ на странице.

    Потом можно немного усложнить, добавить обработку параметров, сделать что-то типа такого...
    Запрос курса валюты.
    В html делаете selectbox, в котором нужно выбрать валюту (доллар или евро), выбранное значение отправляете на сервер. Сервер, в зависимости от указанной валюты, возвращает её курс, который вы опять же отображаете на странице без перезагрузки.

    Когда вы сможете сделать эти задачи- вам станет понятнее как реализовать вашу.