проблема golang postgres pgx с вставкой в таблицу
У меня есть некий код, который выполняет что-то вроде небольшого сервера. Делаю это чтобы научиться сетевому программированию. Я подключил драйвер и тулкит pgx чтобы работать с БД postgresql. Реализация моего сайта такая, я загружаю файлы на сервер, они скачиваются на сервер и в БД пишется информация о файлах, решил начать с unique_id и name_file. Вроде бы получилось, но проблема в следующем, я хотел оптимизировать код, чтобы можно было через горутины записывать эти значения, и в цикле запускается горутина для каждого файла который будет загружен, внутри горутины я скачиваю файл на ПК(в данном случае локальный сервер) и хочу сделать запись формата: INSERT INTO images_client_not_look VALUES ($1,$2) где $1 и $2 я достаю в цикле и подставляю значения. Код работает, но проблема в том, что он записывает только одну из горутин. Вот мой код
package server
import (
"context"
"fmt"
"io"
"log"
"net/http"
"os"
"sync"
"time"
"github.com/jackc/pgx/v4"
)
const MAX_UPLOAD_SIZE = 1073741824 // max size upload 1GB in bytes
func uploadFile(w http.ResponseWriter, r *http.Request) {
var wg sync.WaitGroup
var mu sync.Mutex
// Подключение к БД
ctx := context.Background()
db, err := pgx.Connect(ctx, "postgres://postgres:toor@localhost:5432/photoatlas")
if err != nil {
log.Fatalf("failed to connect database: %v", err)
}
defer db.Close(ctx)
// Здесь заканчивается подключение к БД
time_start := time.Now()
fmt.Printf("Upload start\n")
errs := r.ParseMultipartForm(MAX_UPLOAD_SIZE)
if errs != nil {
fmt.Fprintln(w, errs)
return
}
formdata := r.MultipartForm
files := formdata.File["myFile"]
for i, _ := range files {
wg.Add(1)
go func() {
defer wg.Done()
file, err := files[i].Open()
defer file.Close()
if err != nil {
fmt.Fprintln(w, err)
return
}
filename := fmt.Sprint("'" + files[i].Filename + "'")
// Пытался прикрутить БД, получилось
mu.Lock()
sql := "INSERT INTO images_client_not_look VALUES ($1,$2)"
rows, err := db.Query(ctx, sql, i, filename)
_ = rows
fmt.Println("Загрузил файл", files[i].Filename)
if err != nil {
log.Fatalf("QueryRow failed: %v", err)
}
mu.Unlock()
// end postgres connect
out, err := os.Create("./images/" + files[i].Filename)
defer out.Close()
if err != nil {
fmt.Fprintf(w, "Unable to create the file for writing. Check your write access privilege")
return
}
_, err = io.Copy(out, file)
if err != nil {
fmt.Fprintln(w, err)
return
}
}()
}
wg.Wait()
displayUploadedImage(w, r)
time_end := time.Now().Sub(time_start)
fmt.Printf("Was uploaded %v files\n", len(files))
fmt.Printf("Upload end in %v seconds\n", time_end.Seconds())
}
Я попытался добавить ещё одну группу ожидания для синхронизации задачи, но это не привело к результатам. Я попытался установить мьютекс, но это тоже не помогло. Возможно, я ещё недостаточно хорошо знаю этот пакет и не могу использовать его в полной мере Залил код на GO PLAYGROUND
Ответы (1 шт):
Возможно вы используете го до версии 1.22, где i уже скорее всего имеет значение последней итерации.
Вместо запросов в бд сделайте просто вывод в консоль и посмотрите что у вас там за значения.