Source file src/net/net.go
1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 /* 6 Package net provides a portable interface for network I/O, including 7 TCP/IP, UDP, domain name resolution, and Unix domain sockets. 8 9 Although the package provides access to low-level networking 10 primitives, most clients will need only the basic interface provided 11 by the Dial, Listen, and Accept functions and the associated 12 Conn and Listener interfaces. The crypto/tls package uses 13 the same interfaces and similar Dial and Listen functions. 14 15 The Dial function connects to a server: 16 17 conn, err := net.Dial("tcp", "golang.org:80") 18 if err != nil { 19 // handle error 20 } 21 fmt.Fprintf(conn, "GET / HTTP/1.0\r\n\r\n") 22 status, err := bufio.NewReader(conn).ReadString('\n') 23 // ... 24 25 The Listen function creates servers: 26 27 ln, err := net.Listen("tcp", ":8080") 28 if err != nil { 29 // handle error 30 } 31 for { 32 conn, err := ln.Accept() 33 if err != nil { 34 // handle error 35 } 36 go handleConnection(conn) 37 } 38 39 # Name Resolution 40 41 The method for resolving domain names, whether indirectly with functions like Dial 42 or directly with functions like LookupHost and LookupAddr, varies by operating system. 43 44 On Unix systems, the resolver has two options for resolving names. 45 It can use a pure Go resolver that sends DNS requests directly to the servers 46 listed in /etc/resolv.conf, or it can use a cgo-based resolver that calls C 47 library routines such as getaddrinfo and getnameinfo. 48 49 By default the pure Go resolver is used, because a blocked DNS request consumes 50 only a goroutine, while a blocked C call consumes an operating system thread. 51 When cgo is available, the cgo-based resolver is used instead under a variety of 52 conditions: on systems that do not let programs make direct DNS requests (OS X), 53 when the LOCALDOMAIN environment variable is present (even if empty), 54 when the RES_OPTIONS or HOSTALIASES environment variable is non-empty, 55 when the ASR_CONFIG environment variable is non-empty (OpenBSD only), 56 when /etc/resolv.conf or /etc/nsswitch.conf specify the use of features that the 57 Go resolver does not implement, and when the name being looked up ends in .local 58 or is an mDNS name. 59 60 The resolver decision can be overridden by setting the netdns value of the 61 GODEBUG environment variable (see package runtime) to go or cgo, as in: 62 63 export GODEBUG=netdns=go # force pure Go resolver 64 export GODEBUG=netdns=cgo # force native resolver (cgo, win32) 65 66 The decision can also be forced while building the Go source tree 67 by setting the netgo or netcgo build tag. 68 69 A numeric netdns setting, as in GODEBUG=netdns=1, causes the resolver 70 to print debugging information about its decisions. 71 To force a particular resolver while also printing debugging information, 72 join the two settings by a plus sign, as in GODEBUG=netdns=go+1. 73 74 On Plan 9, the resolver always accesses /net/cs and /net/dns. 75 76 On Windows, in Go 1.18.x and earlier, the resolver always used C 77 library functions, such as GetAddrInfo and DnsQuery. 78 */ 79 package net 80 81 import ( 82 "context" 83 "errors" 84 "internal/poll" 85 "io" 86 "os" 87 "sync" 88 "syscall" 89 "time" 90 ) 91 92 // netGo and netCgo contain the state of the build tags used 93 // to build this binary, and whether cgo is available. 94 // conf.go mirrors these into conf for easier testing. 95 var ( 96 netGo bool // set true in cgo_stub.go for build tag "netgo" (or no cgo) 97 netCgo bool // set true in conf_netcgo.go for build tag "netcgo" 98 ) 99 100 // Addr represents a network end point address. 101 // 102 // The two methods Network and String conventionally return strings 103 // that can be passed as the arguments to Dial, but the exact form 104 // and meaning of the strings is up to the implementation. 105 type Addr interface { 106 Network() string // name of the network (for example, "tcp", "udp") 107 String() string // string form of address (for example, "192.0.2.1:25", "[2001:db8::1]:80") 108 } 109 110 // Conn is a generic stream-oriented network connection. 111 // 112 // Multiple goroutines may invoke methods on a Conn simultaneously. 113 type Conn interface { 114 // Read reads data from the connection. 115 // Read can be made to time out and return an error after a fixed 116 // time limit; see SetDeadline and SetReadDeadline. 117 Read(b []byte) (n int, err error) 118 119 // Write writes data to the connection. 120 // Write can be made to time out and return an error after a fixed 121 // time limit; see SetDeadline and SetWriteDeadline. 122 Write(b []byte) (n int, err error) 123 124 // Close closes the connection. 125 // Any blocked Read or Write operations will be unblocked and return errors. 126 Close() error 127 128 // LocalAddr returns the local network address, if known. 129 LocalAddr() Addr 130 131 // RemoteAddr returns the remote network address, if known. 132 RemoteAddr() Addr 133 134 // SetDeadline sets the read and write deadlines associated 135 // with the connection. It is equivalent to calling both 136 // SetReadDeadline and SetWriteDeadline. 137 // 138 // A deadline is an absolute time after which I/O operations 139 // fail instead of blocking. The deadline applies to all future 140 // and pending I/O, not just the immediately following call to 141 // Read or Write. After a deadline has been exceeded, the 142 // connection can be refreshed by setting a deadline in the future. 143 // 144 // If the deadline is exceeded a call to Read or Write or to other 145 // I/O methods will return an error that wraps os.ErrDeadlineExceeded. 146 // This can be tested using errors.Is(err, os.ErrDeadlineExceeded). 147 // The error's Timeout method will return true, but note that there 148 // are other possible errors for which the Timeout method will 149 // return true even if the deadline has not been exceeded. 150 // 151 // An idle timeout can be implemented by repeatedly extending 152 // the deadline after successful Read or Write calls. 153 // 154 // A zero value for t means I/O operations will not time out. 155 SetDeadline(t time.Time) error 156 157 // SetReadDeadline sets the deadline for future Read calls 158 // and any currently-blocked Read call. 159 // A zero value for t means Read will not time out. 160 SetReadDeadline(t time.Time) error 161 162 // SetWriteDeadline sets the deadline for future Write calls 163 // and any currently-blocked Write call. 164 // Even if write times out, it may return n > 0, indicating that 165 // some of the data was successfully written. 166 // A zero value for t means Write will not time out. 167 SetWriteDeadline(t time.Time) error 168 } 169 170 type conn struct { 171 fd *netFD 172 } 173 174 func (c *conn) ok() bool { return c != nil && c.fd != nil } 175 176 // Implementation of the Conn interface. 177 178 // Read implements the Conn Read method. 179 func (c *conn) Read(b []byte) (int, error) { 180 if !c.ok() { 181 return 0, syscall.EINVAL 182 } 183 n, err := c.fd.Read(b) 184 if err != nil && err != io.EOF { 185 err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err} 186 } 187 return n, err 188 } 189 190 // Write implements the Conn Write method. 191 func (c *conn) Write(b []byte) (int, error) { 192 if !c.ok() { 193 return 0, syscall.EINVAL 194 } 195 n, err := c.fd.Write(b) 196 if err != nil { 197 err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err} 198 } 199 return n, err 200 } 201 202 // Close closes the connection. 203 func (c *conn) Close() error { 204 if !c.ok() { 205 return syscall.EINVAL 206 } 207 err := c.fd.Close() 208 if err != nil { 209 err = &OpError{Op: "close", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err} 210 } 211 return err 212 } 213 214 // LocalAddr returns the local network address. 215 // The Addr returned is shared by all invocations of LocalAddr, so 216 // do not modify it. 217 func (c *conn) LocalAddr() Addr { 218 if !c.ok() { 219 return nil 220 } 221 return c.fd.laddr 222 } 223 224 // RemoteAddr returns the remote network address. 225 // The Addr returned is shared by all invocations of RemoteAddr, so 226 // do not modify it. 227 func (c *conn) RemoteAddr() Addr { 228 if !c.ok() { 229 return nil 230 } 231 return c.fd.raddr 232 } 233 234 // SetDeadline implements the Conn SetDeadline method. 235 func (c *conn) SetDeadline(t time.Time) error { 236 if !c.ok() { 237 return syscall.EINVAL 238 } 239 if err := c.fd.SetDeadline(t); err != nil { 240 return &OpError{Op: "set", Net: c.fd.net, Source: nil, Addr: c.fd.laddr, Err: err} 241 } 242 return nil 243 } 244 245 // SetReadDeadline implements the Conn SetReadDeadline method. 246 func (c *conn) SetReadDeadline(t time.Time) error { 247 if !c.ok() { 248 return syscall.EINVAL 249 } 250 if err := c.fd.SetReadDeadline(t); err != nil { 251 return &OpError{Op: "set", Net: c.fd.net, Source: nil, Addr: c.fd.laddr, Err: err} 252 } 253 return nil 254 } 255 256 // SetWriteDeadline implements the Conn SetWriteDeadline method. 257 func (c *conn) SetWriteDeadline(t time.Time) error { 258 if !c.ok() { 259 return syscall.EINVAL 260 } 261 if err := c.fd.SetWriteDeadline(t); err != nil { 262 return &OpError{Op: "set", Net: c.fd.net, Source: nil, Addr: c.fd.laddr, Err: err} 263 } 264 return nil 265 } 266 267 // SetReadBuffer sets the size of the operating system's 268 // receive buffer associated with the connection. 269 func (c *conn) SetReadBuffer(bytes int) error { 270 if !c.ok() { 271 return syscall.EINVAL 272 } 273 if err := setReadBuffer(c.fd, bytes); err != nil { 274 return &OpError{Op: "set", Net: c.fd.net, Source: nil, Addr: c.fd.laddr, Err: err} 275 } 276 return nil 277 } 278 279 // SetWriteBuffer sets the size of the operating system's 280 // transmit buffer associated with the connection. 281 func (c *conn) SetWriteBuffer(bytes int) error { 282 if !c.ok() { 283 return syscall.EINVAL 284 } 285 if err := setWriteBuffer(c.fd, bytes); err != nil { 286 return &OpError{Op: "set", Net: c.fd.net, Source: nil, Addr: c.fd.laddr, Err: err} 287 } 288 return nil 289 } 290 291 // File returns a copy of the underlying os.File. 292 // It is the caller's responsibility to close f when finished. 293 // Closing c does not affect f, and closing f does not affect c. 294 // 295 // The returned os.File's file descriptor is different from the connection's. 296 // Attempting to change properties of the original using this duplicate 297 // may or may not have the desired effect. 298 func (c *conn) File() (f *os.File, err error) { 299 f, err = c.fd.dup() 300 if err != nil { 301 err = &OpError{Op: "file", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err} 302 } 303 return 304 } 305 306 // PacketConn is a generic packet-oriented network connection. 307 // 308 // Multiple goroutines may invoke methods on a PacketConn simultaneously. 309 type PacketConn interface { 310 // ReadFrom reads a packet from the connection, 311 // copying the payload into p. It returns the number of 312 // bytes copied into p and the return address that 313 // was on the packet. 314 // It returns the number of bytes read (0 <= n <= len(p)) 315 // and any error encountered. Callers should always process 316 // the n > 0 bytes returned before considering the error err. 317 // ReadFrom can be made to time out and return an error after a 318 // fixed time limit; see SetDeadline and SetReadDeadline. 319 ReadFrom(p []byte) (n int, addr Addr, err error) 320 321 // WriteTo writes a packet with payload p to addr. 322 // WriteTo can be made to time out and return an Error after a 323 // fixed time limit; see SetDeadline and SetWriteDeadline. 324 // On packet-oriented connections, write timeouts are rare. 325 WriteTo(p []byte, addr Addr) (n int, err error) 326 327 // Close closes the connection. 328 // Any blocked ReadFrom or WriteTo operations will be unblocked and return errors. 329 Close() error 330 331 // LocalAddr returns the local network address, if known. 332 LocalAddr() Addr 333 334 // SetDeadline sets the read and write deadlines associated 335 // with the connection. It is equivalent to calling both 336 // SetReadDeadline and SetWriteDeadline. 337 // 338 // A deadline is an absolute time after which I/O operations 339 // fail instead of blocking. The deadline applies to all future 340 // and pending I/O, not just the immediately following call to 341 // Read or Write. After a deadline has been exceeded, the 342 // connection can be refreshed by setting a deadline in the future. 343 // 344 // If the deadline is exceeded a call to Read or Write or to other 345 // I/O methods will return an error that wraps os.ErrDeadlineExceeded. 346 // This can be tested using errors.Is(err, os.ErrDeadlineExceeded). 347 // The error's Timeout method will return true, but note that there 348 // are other possible errors for which the Timeout method will 349 // return true even if the deadline has not been exceeded. 350 // 351 // An idle timeout can be implemented by repeatedly extending 352 // the deadline after successful ReadFrom or WriteTo calls. 353 // 354 // A zero value for t means I/O operations will not time out. 355 SetDeadline(t time.Time) error 356 357 // SetReadDeadline sets the deadline for future ReadFrom calls 358 // and any currently-blocked ReadFrom call. 359 // A zero value for t means ReadFrom will not time out. 360 SetReadDeadline(t time.Time) error 361 362 // SetWriteDeadline sets the deadline for future WriteTo calls 363 // and any currently-blocked WriteTo call. 364 // Even if write times out, it may return n > 0, indicating that 365 // some of the data was successfully written. 366 // A zero value for t means WriteTo will not time out. 367 SetWriteDeadline(t time.Time) error 368 } 369 370 var listenerBacklogCache struct { 371 sync.Once 372 val int 373 } 374 375 // listenerBacklog is a caching wrapper around maxListenerBacklog. 376 func listenerBacklog() int { 377 listenerBacklogCache.Do(func() { listenerBacklogCache.val = maxListenerBacklog() }) 378 return listenerBacklogCache.val 379 } 380 381 // A Listener is a generic network listener for stream-oriented protocols. 382 // 383 // Multiple goroutines may invoke methods on a Listener simultaneously. 384 type Listener interface { 385 // Accept waits for and returns the next connection to the listener. 386 Accept() (Conn, error) 387 388 // Close closes the listener. 389 // Any blocked Accept operations will be unblocked and return errors. 390 Close() error 391 392 // Addr returns the listener's network address. 393 Addr() Addr 394 } 395 396 // An Error represents a network error. 397 type Error interface { 398 error 399 Timeout() bool // Is the error a timeout? 400 401 // Deprecated: Temporary errors are not well-defined. 402 // Most "temporary" errors are timeouts, and the few exceptions are surprising. 403 // Do not use this method. 404 Temporary() bool 405 } 406 407 // Various errors contained in OpError. 408 var ( 409 // For connection setup operations. 410 errNoSuitableAddress = errors.New("no suitable address found") 411 412 // For connection setup and write operations. 413 errMissingAddress = errors.New("missing address") 414 415 // For both read and write operations. 416 errCanceled = canceledError{} 417 ErrWriteToConnected = errors.New("use of WriteTo with pre-connected connection") 418 ) 419 420 // canceledError lets us return the same error string we have always 421 // returned, while still being Is context.Canceled. 422 type canceledError struct{} 423 424 func (canceledError) Error() string { return "operation was canceled" } 425 426 func (canceledError) Is(err error) bool { return err == context.Canceled } 427 428 // mapErr maps from the context errors to the historical internal net 429 // error values. 430 func mapErr(err error) error { 431 switch err { 432 case context.Canceled: 433 return errCanceled 434 case context.DeadlineExceeded: 435 return errTimeout 436 default: 437 return err 438 } 439 } 440 441 // OpError is the error type usually returned by functions in the net 442 // package. It describes the operation, network type, and address of 443 // an error. 444 type OpError struct { 445 // Op is the operation which caused the error, such as 446 // "read" or "write". 447 Op string 448 449 // Net is the network type on which this error occurred, 450 // such as "tcp" or "udp6". 451 Net string 452 453 // For operations involving a remote network connection, like 454 // Dial, Read, or Write, Source is the corresponding local 455 // network address. 456 Source Addr 457 458 // Addr is the network address for which this error occurred. 459 // For local operations, like Listen or SetDeadline, Addr is 460 // the address of the local endpoint being manipulated. 461 // For operations involving a remote network connection, like 462 // Dial, Read, or Write, Addr is the remote address of that 463 // connection. 464 Addr Addr 465 466 // Err is the error that occurred during the operation. 467 // The Error method panics if the error is nil. 468 Err error 469 } 470 471 func (e *OpError) Unwrap() error { return e.Err } 472 473 func (e *OpError) Error() string { 474 if e == nil { 475 return "<nil>" 476 } 477 s := e.Op 478 if e.Net != "" { 479 s += " " + e.Net 480 } 481 if e.Source != nil { 482 s += " " + e.Source.String() 483 } 484 if e.Addr != nil { 485 if e.Source != nil { 486 s += "->" 487 } else { 488 s += " " 489 } 490 s += e.Addr.String() 491 } 492 s += ": " + e.Err.Error() 493 return s 494 } 495 496 var ( 497 // aLongTimeAgo is a non-zero time, far in the past, used for 498 // immediate cancellation of dials. 499 aLongTimeAgo = time.Unix(1, 0) 500 501 // noDeadline and noCancel are just zero values for 502 // readability with functions taking too many parameters. 503 noDeadline = time.Time{} 504 noCancel = (chan struct{})(nil) 505 ) 506 507 type timeout interface { 508 Timeout() bool 509 } 510 511 func (e *OpError) Timeout() bool { 512 if ne, ok := e.Err.(*os.SyscallError); ok { 513 t, ok := ne.Err.(timeout) 514 return ok && t.Timeout() 515 } 516 t, ok := e.Err.(timeout) 517 return ok && t.Timeout() 518 } 519 520 type temporary interface { 521 Temporary() bool 522 } 523 524 func (e *OpError) Temporary() bool { 525 // Treat ECONNRESET and ECONNABORTED as temporary errors when 526 // they come from calling accept. See issue 6163. 527 if e.Op == "accept" && isConnError(e.Err) { 528 return true 529 } 530 531 if ne, ok := e.Err.(*os.SyscallError); ok { 532 t, ok := ne.Err.(temporary) 533 return ok && t.Temporary() 534 } 535 t, ok := e.Err.(temporary) 536 return ok && t.Temporary() 537 } 538 539 // A ParseError is the error type of literal network address parsers. 540 type ParseError struct { 541 // Type is the type of string that was expected, such as 542 // "IP address", "CIDR address". 543 Type string 544 545 // Text is the malformed text string. 546 Text string 547 } 548 549 func (e *ParseError) Error() string { return "invalid " + e.Type + ": " + e.Text } 550 551 func (e *ParseError) Timeout() bool { return false } 552 func (e *ParseError) Temporary() bool { return false } 553 554 type AddrError struct { 555 Err string 556 Addr string 557 } 558 559 func (e *AddrError) Error() string { 560 if e == nil { 561 return "<nil>" 562 } 563 s := e.Err 564 if e.Addr != "" { 565 s = "address " + e.Addr + ": " + s 566 } 567 return s 568 } 569 570 func (e *AddrError) Timeout() bool { return false } 571 func (e *AddrError) Temporary() bool { return false } 572 573 type UnknownNetworkError string 574 575 func (e UnknownNetworkError) Error() string { return "unknown network " + string(e) } 576 func (e UnknownNetworkError) Timeout() bool { return false } 577 func (e UnknownNetworkError) Temporary() bool { return false } 578 579 type InvalidAddrError string 580 581 func (e InvalidAddrError) Error() string { return string(e) } 582 func (e InvalidAddrError) Timeout() bool { return false } 583 func (e InvalidAddrError) Temporary() bool { return false } 584 585 // errTimeout exists to return the historical "i/o timeout" string 586 // for context.DeadlineExceeded. See mapErr. 587 // It is also used when Dialer.Deadline is exceeded. 588 // error.Is(errTimeout, context.DeadlineExceeded) returns true. 589 // 590 // TODO(iant): We could consider changing this to os.ErrDeadlineExceeded 591 // in the future, if we make 592 // 593 // errors.Is(os.ErrDeadlineExceeded, context.DeadlineExceeded) 594 // 595 // return true. 596 var errTimeout error = &timeoutError{} 597 598 type timeoutError struct{} 599 600 func (e *timeoutError) Error() string { return "i/o timeout" } 601 func (e *timeoutError) Timeout() bool { return true } 602 func (e *timeoutError) Temporary() bool { return true } 603 604 func (e *timeoutError) Is(err error) bool { 605 return err == context.DeadlineExceeded 606 } 607 608 // DNSConfigError represents an error reading the machine's DNS configuration. 609 // (No longer used; kept for compatibility.) 610 type DNSConfigError struct { 611 Err error 612 } 613 614 func (e *DNSConfigError) Unwrap() error { return e.Err } 615 func (e *DNSConfigError) Error() string { return "error reading DNS config: " + e.Err.Error() } 616 func (e *DNSConfigError) Timeout() bool { return false } 617 func (e *DNSConfigError) Temporary() bool { return false } 618 619 // Various errors contained in DNSError. 620 var ( 621 errNoSuchHost = errors.New("no such host") 622 ) 623 624 // DNSError represents a DNS lookup error. 625 type DNSError struct { 626 Err string // description of the error 627 Name string // name looked for 628 Server string // server used 629 IsTimeout bool // if true, timed out; not all timeouts set this 630 IsTemporary bool // if true, error is temporary; not all errors set this 631 IsNotFound bool // if true, host could not be found 632 } 633 634 func (e *DNSError) Error() string { 635 if e == nil { 636 return "<nil>" 637 } 638 s := "lookup " + e.Name 639 if e.Server != "" { 640 s += " on " + e.Server 641 } 642 s += ": " + e.Err 643 return s 644 } 645 646 // Timeout reports whether the DNS lookup is known to have timed out. 647 // This is not always known; a DNS lookup may fail due to a timeout 648 // and return a DNSError for which Timeout returns false. 649 func (e *DNSError) Timeout() bool { return e.IsTimeout } 650 651 // Temporary reports whether the DNS error is known to be temporary. 652 // This is not always known; a DNS lookup may fail due to a temporary 653 // error and return a DNSError for which Temporary returns false. 654 func (e *DNSError) Temporary() bool { return e.IsTimeout || e.IsTemporary } 655 656 // errClosed exists just so that the docs for ErrClosed don't mention 657 // the internal package poll. 658 var errClosed = poll.ErrNetClosing 659 660 // ErrClosed is the error returned by an I/O call on a network 661 // connection that has already been closed, or that is closed by 662 // another goroutine before the I/O is completed. This may be wrapped 663 // in another error, and should normally be tested using 664 // errors.Is(err, net.ErrClosed). 665 var ErrClosed error = errClosed 666 667 type writerOnly struct { 668 io.Writer 669 } 670 671 // Fallback implementation of io.ReaderFrom's ReadFrom, when sendfile isn't 672 // applicable. 673 func genericReadFrom(w io.Writer, r io.Reader) (n int64, err error) { 674 // Use wrapper to hide existing r.ReadFrom from io.Copy. 675 return io.Copy(writerOnly{w}, r) 676 } 677 678 // Limit the number of concurrent cgo-using goroutines, because 679 // each will block an entire operating system thread. The usual culprit 680 // is resolving many DNS names in separate goroutines but the DNS 681 // server is not responding. Then the many lookups each use a different 682 // thread, and the system or the program runs out of threads. 683 684 var threadLimit chan struct{} 685 686 var threadOnce sync.Once 687 688 func acquireThread() { 689 threadOnce.Do(func() { 690 threadLimit = make(chan struct{}, concurrentThreadsLimit()) 691 }) 692 threadLimit <- struct{}{} 693 } 694 695 func releaseThread() { 696 <-threadLimit 697 } 698 699 // buffersWriter is the interface implemented by Conns that support a 700 // "writev"-like batch write optimization. 701 // writeBuffers should fully consume and write all chunks from the 702 // provided Buffers, else it should report a non-nil error. 703 type buffersWriter interface { 704 writeBuffers(*Buffers) (int64, error) 705 } 706 707 // Buffers contains zero or more runs of bytes to write. 708 // 709 // On certain machines, for certain types of connections, this is 710 // optimized into an OS-specific batch write operation (such as 711 // "writev"). 712 type Buffers [][]byte 713 714 var ( 715 _ io.WriterTo = (*Buffers)(nil) 716 _ io.Reader = (*Buffers)(nil) 717 ) 718 719 // WriteTo writes contents of the buffers to w. 720 // 721 // WriteTo implements io.WriterTo for Buffers. 722 // 723 // WriteTo modifies the slice v as well as v[i] for 0 <= i < len(v), 724 // but does not modify v[i][j] for any i, j. 725 func (v *Buffers) WriteTo(w io.Writer) (n int64, err error) { 726 if wv, ok := w.(buffersWriter); ok { 727 return wv.writeBuffers(v) 728 } 729 for _, b := range *v { 730 nb, err := w.Write(b) 731 n += int64(nb) 732 if err != nil { 733 v.consume(n) 734 return n, err 735 } 736 } 737 v.consume(n) 738 return n, nil 739 } 740 741 // Read from the buffers. 742 // 743 // Read implements io.Reader for Buffers. 744 // 745 // Read modifies the slice v as well as v[i] for 0 <= i < len(v), 746 // but does not modify v[i][j] for any i, j. 747 func (v *Buffers) Read(p []byte) (n int, err error) { 748 for len(p) > 0 && len(*v) > 0 { 749 n0 := copy(p, (*v)[0]) 750 v.consume(int64(n0)) 751 p = p[n0:] 752 n += n0 753 } 754 if len(*v) == 0 { 755 err = io.EOF 756 } 757 return 758 } 759 760 func (v *Buffers) consume(n int64) { 761 for len(*v) > 0 { 762 ln0 := int64(len((*v)[0])) 763 if ln0 > n { 764 (*v)[0] = (*v)[0][n:] 765 return 766 } 767 n -= ln0 768 (*v)[0] = nil 769 *v = (*v)[1:] 770 } 771 } 772