您的位置 首页 golang

io包 copy – golang

在io包中主要是操作流的一些方法,今天主要学习一下copy。

在io包(golang 版本 1.12)中,提供了3个公开的copy方法:CopyN(),Copy(),CopyBuffer().

CopyN(dst,src,n) 为复制src 中 n 个字节到 dst。

Copy(dst,src) 为复制src 全部到 dst 中。

CopyBuffer(dst,src,buf)为指定一个buf缓存区,以这个大小完全复制。

他们的关系如下:

从图可以看出,无论是哪个copy方法最终都是由copyBuffer()这个私有方法实现的。下面我们看看这个方法的源码。

 func copyBuffer(dst Writer, src Reader, buf [] byte ) (written int64, err error) {

 	// If the reader has a WriteTo method, use it to do the copy.

 	// Avoids an allocation and a copy.

 	if wt, ok := src.(WriterTo); ok {

 		return wt.WriteTo(dst)

 	}

 	// Similarly, if the writer has a ReadFrom method, use it to do the copy.

 	if rt, ok := dst.(ReaderFrom); ok {

 		return rt.ReadFrom(src)

 	}

 	if buf ==  nil  {

 		size := 32 * 1024

 		if l, ok := src.(*LimitedReader); ok && int64(size) > l.N {

 			if l.N < 1 {

 				size = 1

 			} else {

 				size = int(l.N)

 			}

 		}

 		buf = make([]byte, size)

 	}

 	for {

 		nr, er := src.Read(buf)

 		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 = ErrShortWrite

 				break

 			}

 		}

 		if er != nil {

 			if er !=  EOF  {

 				err = er

 			}

 			break

 		}

 	}

 	return written, err

 } 

从这部分代码可以看出,复制主要分为3种。

1.如果被复制的Reader(src)会尝试能否断言成writerTo,如果可以则直接调用下面的writerTo方法

2.如果 Writer(dst) 会尝试能否断言成ReadFrom ,如果可以则直接调用下面的readfrom方法

3.如果都木有实现,则调用底层read实现复制。

其中,有这么一段代码:

if buf == nil {

 		size := 32 * 1024

 		if l, ok := src.(*LimitedReader); ok && int64(size) > l.N {

 			if l.N < 1 {

 				size = 1

 			} else {

 				size = int(l.N)

 			}

 		}

 		buf = make([]byte, size)

 	}  

这部分主要是实现了对Copy和CopyN的处理。通过上面的调用关系图,我们看出CopyN在调用后,会把Reader转成LimiteReader。

区别是如果Copy,直接建立一个缓存区默认大小为 32* 1024 的buf,如果是CopyN 会先判断 要复制的字节数 如果小于默认大小,会创建一个等于要复制字节数的buf。

文章来源:智云一二三科技

文章标题:io包 copy – golang

文章地址:https://www.zhihuclub.com/100386.shtml

关于作者: 智云科技

热门文章

网站地图