如何停止io.CopyN

huangapple go评论83阅读模式
英文:

How to stop io.CopyN

问题

我有一些代码,从文件复制到tcp套接字(类似于ftp服务器),如果需要,希望能够中止此复制。

我只是使用io.CopyN(socket, file, size),看不到任何中止信号的方法。有什么想法吗?

英文:

I have some code that copies from a file to a tcp socket (like an ftp server) and want to be able to abort this copy if needed.

Im just using io.CopyN(socket, file, size) and cant see a way to signal an abort. Any ideas?

答案1

得分: 6

如何只关闭输入文件?io.CopyN将返回一个错误并中止。

这是一个演示(如果不在Linux上运行,请将/dev/zero/dev/null更改为您的操作系统等效物!)

package main

import (
	"fmt"
	"io"
	"log"
	"os"
	"time"
)

func main() {
	in, err := os.Open("/dev/zero")
	if err != nil {
		log.Fatal(err)
	}

	out, err := os.Create("/dev/null")
	if err != nil {
		log.Fatal(err)
	}

	go func() {
		time.Sleep(time.Second)
		in.Close()
	}()

	written, err := io.CopyN(out, in, 1E12)
	fmt.Printf("%d 字节已写入,错误为 %s\n", written, err)
}

运行时,它将打印类似以下内容:

9756147712 字节已写入,错误为 read /dev/zero: bad file descriptor
英文:

How about just closing the input file? io.CopyN will then return an error and abort.

Here is a demonstration (If not running on Linux change /dev/zero & /dev/null for your OS equivalent!)

package main

import (
	"fmt"
	"io"
	"log"
	"os"
	"time"
)

func main() {
	in, err := os.Open("/dev/zero")
	if err != nil {
		log.Fatal(err)
	}

	out, err := os.Create("/dev/null")
	if err != nil {
		log.Fatal(err)
	}

	go func() {
		time.Sleep(time.Second)
		in.Close()
	}()

	written, err := io.CopyN(out, in, 1E12)
	fmt.Printf("%d bytes written with error %s\n", written, err)
}

When run it will print something like

9756147712 bytes written with error read /dev/zero: bad file descriptor

答案2

得分: 4

CopyN努力复制N个字节。如果您想选择性地复制少于N个字节,则首先不要使用CopyN。我可能会将原始代码改为以下内容(未经测试的代码):

func copyUpToN(dst Writer, src Reader, n int64, signal chan int) (written int64, err error) {
    buf := make([]byte, 32*1024)
    for written < n {
        select {
        default:
        case <-signal:
            return 0, fmt.Errorf("Aborted") // 或其他适当的错误信息
        }

        l := len(buf)
        if d := n - written; d < int64(l) {
            l = int(d)
        }
        nr, er := src.Read(buf[0:l])
        if nr > 0 {
            nw, ew := dst.Write(buf[0:nr])
            if nw > 0 {
                written += int64(nw)
            }
            if ew != nil {
                err = ew
                break
            }
            if nr != nw {
                err = io.ErrShortWrite
                break
            }
        }
        if er != nil {
            err = er
            break
        }
    }
    return written, err
}
英文:

CopyN tries hard to copy N bytes. If you want to optionally copy less than N bytes then don't use CopyN in the first place. I would probably adapt the original code to something like (untested code):

func copyUpToN(dst Writer, src Reader, n int64, signal chan int) (written int64, err error) {
	buf := make([]byte, 32*1024)
	for written &lt; n {
		select {
		default:
		case &lt;-signal:
			return 0, fmt.Errorf(&quot;Aborted&quot;) // or whatever
		}

		l := len(buf)
		if d := n - written; d &lt; int64(l) {
			l = int(d)
		}
		nr, er := src.Read(buf[0:l])
		if nr &gt; 0 {
			nw, ew := dst.Write(buf[0:nr])
			if nw &gt; 0 {
				written += int64(nw)
			}
			if ew != nil {
				err = ew
				break
			}
			if nr != nw {
				err = io.ErrShortWrite
				break
			}
		}
		if er != nil {
			err = er
			break
		}
	}
	return written, err
}

huangapple
  • 本文由 发表于 2013年2月10日 17:30:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/14796337.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定