Maison > développement back-end > Golang > le corps du texte

Go - Utilisation correcte de Part.Read en plusieurs parties

王林
Libérer: 2024-02-09 08:18:27
avant
1067 Les gens l'ont consulté

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
                }
            }
        }
    }
}

Copier après la connexion

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().

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

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)
}
Copier après la connexion

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!

Étiquettes associées:
source:stackoverflow.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal