首頁 > 後端開發 > Golang > 主體

Go 中的「http:寫入超過聲明的 Content-Length」錯誤

WBOY
發布: 2024-02-09 12:50:07
轉載
676 人瀏覽過

Go 中的“http:写入超过声明的 Content-Length”错误

php小編新一今天將為大家介紹一個常見的錯誤,也就是在Go語言中出現的「http:寫入超過宣告的Content-Length」錯誤。當我們在使用Go語言來寫HTTP請求時,有時會遇到這個錯誤。這個錯誤的原因是我們在請求頭中聲明的Content-Length與實際發送的請求體長度不一致。接下來,我們將詳細解釋這個錯誤的產生原因以及如何解決它。

問題內容

我正在嘗試 Go 並編寫了一個應用程式來管理由工作協程處理的 HTTP 請求佇列。

並發的東西似乎工作正常,但在發送回 http 回應時出現此錯誤:寫入的內容超過聲明的 Content-Length

完整程式碼如下:

package main

import (
    "log"
    "net/http"
    "sync"
)

// Job represents a unit of work to be processed by a worker.
type Job struct {
    r *http.Request       // HTTP request to be processed
    w http.ResponseWriter // Response writer to send the result
}

// Queue manages a list of jobs to be processed by workers.
type Queue struct {
    jobs []*Job     // List of jobs in the queue
    mu   sync.Mutex // Mutex to synchronize access to the queue
    cond *sync.Cond // Condition variable for signaling
}

var q Queue // Global instance of the queue
var WORKER_POOL_SIZE = 4 // Number of workers

// Push adds a job to the queue.
func (q *Queue) Push(j *Job) {
    q.mu.Lock()
    defer q.mu.Unlock()
    q.jobs = append(q.jobs, j)
    q.cond.Signal() // Signal a waiting worker that a job is available
    log.Println("Job added to queue")
}

// Pop retrieves and removes a job from the queue.
func (q *Queue) Pop() (*Job, bool) {
    q.mu.Lock()
    defer q.mu.Unlock()
    if len(q.jobs) == 0 {
        q.cond.Wait() // If the queue is empty, wait for a signal
    }
    job := q.jobs[0]
    q.jobs = q.jobs[1:]
    log.Println("Job removed from queue")
    return job, true
}

// handler adds a job to the queue.
func handler(w http.ResponseWriter, r *http.Request) {
    // Create a job with the request and response.
    job := &Job{r, w}

    // Push the job onto the queue.
    q.Push(job)
    log.Println("Received request and added job to queue")
}

// init initializes the condition variable and starts worker goroutines.
func init() {
    q.cond = sync.NewCond(&q.mu)
    for i := 0; i < WORKER_POOL_SIZE; i++ {
        go worker()
    }
}

// worker processes jobs from the queue.
func worker() {
    for {
        job, ok := q.Pop()
        if ok {
            log.Println("Worker processing job")
            doWork(job)
        }
    }
}

// doWork simulates processing a job and sends a response.
func doWork(job *Job) {
    // Extract the "Name" parameter from the request query.
    name := job.r.URL.Query().Get("Name")

    // Check if the name is not empty.
    if name != "" {
        // Send the name as the response.
        _, err := job.w.Write([]byte("Hello, " + name))
        if err != nil {
            log.Println("Error writing response:", err)
        }
        log.Println("Response sent: Hello,", name)
    } else {
        // If the "Name" parameter is missing or empty, send an error response.
        http.Error(job.w, "Name parameter is missing or empty", http.StatusBadRequest)
        log.Println("Error: Name parameter is missing or empty")
    }
}

func main() {
    http.HandleFunc("/addJob", handler)
    log.Println("Server started and listening on :8080")
    err := http.ListenAndServe(":8080", nil)
    if err != nil {
        log.Fatal("Error starting server:", err)
    }
}

登入後複製

知道如何解決這個問題嗎?另外,由於我對 go 中的並發性很陌生,你認為它可以改進嗎?謝謝!

解決方法

根據 http.Handler 文件

您的 handler 正在將請求/編寫器推送到佇列中,然後返回。這表示您在處理程序返回後嘗試寫入 ResponseWriter ,違反了上述規定(由於沒有同步,寫入也可能實際發生在 return 之前或同時發生)。

有很多方法可以解決這個問題;一種技術是:

// Job represents a unit of work to be processed by a worker.
type Job struct {
    r    *http.Request       // HTTP request to be processed
    w    http.ResponseWriter // Response writer to send the result
    done chan struct{}       // Closed when write competed
}

...

func handler(w http.ResponseWriter, r *http.Request) {
    // Create a job with the request and response.
    job := &Job{r, w, make(chan struct{})}

    // Push the job onto the queue.
    q.Push(job)
    log.Println("Received request and added job to queue")
    <-job.done // Wait until job has been processed
}

...

// worker processes jobs from the queue.
func worker() {
    for {
        job, ok := q.Pop()
        if ok {
            log.Println("Worker processing job")
            doWork(job)
            close(job.done) // Notify requester that we are done
        }
    }
}
登入後複製

這實際上取決於要求。一個常見的解決方案是僅使用通道(處理程序將請求發送到通道,多個工作人員從同一通道接收)。

以上是Go 中的「http:寫入超過聲明的 Content-Length」錯誤的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:stackoverflow.com
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
最新問題
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!