Maison  >  Article  >  développement back-end  >  Go - Utilisation correcte de Part.Read en plusieurs parties

Go - Utilisation correcte de Part.Read en plusieurs parties

王林
王林avant
2024-02-09 08:18:271036parcourir

Go - 多部分 Part.Read 的正确用法

L'éditeur php Xinyi vous présentera aujourd'hui l'utilisation correcte du langage Part.Read en plusieurs parties dans le langage Go. Lors du traitement des requêtes HTTP, nous rencontrons souvent des situations dans lesquelles nous devons lire plusieurs parties de données, comme le traitement des téléchargements de fichiers. Le package net/http du langage Go fournit la méthode Part.Read pour lire des données en plusieurs parties, mais de nombreux développeurs rencontreront des problèmes lors de son utilisation. Cet article expliquera en détail l'utilisation correcte de Part.Read pour aider les développeurs à mieux gérer les données en plusieurs parties et à améliorer la stabilité et les performances du programme. Nous allons jeter un coup d'oeil!

Contenu de la question

J'ai essayé d'utiliser multipart.part pour faciliter la lecture depuis http pour les téléchargements de fichiers très volumineux (> 20 Go) - j'ai donc écrit le code suivant et il semble bien fonctionner :

func ReceiveMultipartRoute(w http.ResponseWriter, r *http.Request) {
    mediatype, p, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
    if err != nil {
       //...
    }
    if mediatype != "multipart/form-data" {
        //...
    }
    boundary := p["boundary"]
    reader := multipart.NewReader(r.Body, boundary)
    buffer := make([]byte, 8192)
    for {
        part, err := reader.NextPart()
        if err != nil {
            // ... 
        }
    
        f, err := os.CreateTemp("", part.FileName())
        if err != nil {
            // ...
        }
    
        for {
            numBytesRead, err := part.Read(buffer)
            // People say not to read if there's an err, but then I miss the last chunk?
            f.Write(buffer[:numBytesRead])
            if err != nil {
                if err == io.EOF {
                    break
                } else {
                    // error, abort ...
                    return
                }
            }
        }
    }
}

Cependant, dans la boucle for la plus interne, j'ai découvert que je devais lire part.read avant de vérifier eof car j'ai remarqué que si je faisais cela avant et que je cassais, je manquerais le dernier bloc. Cependant, j'ai remarqué dans de nombreux autres articles/posts que les gens vérifient les erreurs/eof et vérifient break-ing le cas échéant sans utiliser la dernière lecture. Est-ce que j'utilise multipart.part.read() de manière incorrecte/en toute sécurité ?

Solution

Vous utilisez multipart.part de la bonne manière.

multipart.part est une spécifique implémentation de go.dev/io#reader" rel="nofollow noreferrer">io.reader. Par conséquent, vous devez suivre la convention et suivre les recommandations de io. lecteur. Cité dans la documentation :

Les appelants doivent toujours gérer n > 0 octets renvoyés avant de considérer une erreur d’erreur. Cela permet une gestion correcte des erreurs d'E/S qui se produisent après la lecture de certains octets ainsi que le comportement eof autorisé.

Notez également que dans l'exemple, vous copiez des données de io.reader vers os.file. os.file implémente l'interface io.readerfrom, afin que vous puissiez copier des données à l'aide de la méthode file.readfrom(). p>

_, err := file.readfrom(part)
// non io.eof
if err != nil {
    return fmt.errorf("copy data: %w", err)
}

Si vous avez besoin d'utiliser un tampon, vous pouvez utiliser la fonction io.copybuffer(). Notez cependant que vous devez masquer l'implémentation io.readerfrom, sinon le tampon n'utilisera pas pour effectuer la copie. Voir exemples : 1, 2, 3.

_, err := io.CopyBuffer(writeFunc(file.Write), part, buffer)
// non io.EOF
if err != nil {
    return fmt.Errorf("copy data: %w", err)
}

type writeFunc func([]byte) (int, error)

func (write writeFunc) Write(data []byte) (int, error) {
        return write(data)
}

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer