проблема 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 уже скорее всего имеет значение последней итерации.

Вместо запросов в бд сделайте просто вывод в консоль и посмотрите что у вас там за значения.

→ Ссылка