<input name="user_forms[0][surname]" .. />
?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()
}
s := Server{servers: []*HTTPServer{}}
// После чего нужно добавить "слушателей".
l := net.Listen("tcp", ":3001")
s.Accept(":3001", l)
// после чего вызывать
s.serveAPI()
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")
}
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()
}
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))
Хорошо бы, для начала понять, сколько памяти реально течёт, есть сомнения, что эта map'а, занимает много памяти.
> Эта функция запускается сразу в большом кол-ве горутин (go scan())
Также нужно понять сколько горутин запускается?
Почему? Потому, что каждая из них, в зависимости от размера стэка, потребляет память.
Если их запускается очень много и/или, например, они не завершаются, вот тут уже более реальна "огромная" утечка памяти.