Zero-Copy File Server

io.Copy from an *os.File to a *net.TCPConn hands the transfer to the kernel's sendfile, so a megabyte moves to the socket without ever passing through your program's memory. The client counts the bytes it receives.

package main

import (
	"fmt"
	"io"
	"net"
	"os"
	"strings"
)

func main() {
	// A 1 MiB file to serve.
	f, _ := os.CreateTemp("", "payload")
	defer os.Remove(f.Name())
	f.WriteString(strings.Repeat("x", 1<<20))
	f.Close()

	ln, err := net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		fmt.Println("listen:", err)
		return
	}
	defer ln.Close()

	// Server: io.Copy(*os.File -> *net.TCPConn) uses sendfile, in-kernel.
	go func() {
		conn, err := ln.Accept()
		if err != nil {
			return
		}
		defer conn.Close()
		file, _ := os.Open(f.Name())
		defer file.Close()
		n, _ := io.Copy(conn, file) // no user-space buffer involved
		fmt.Println("server sent", n, "bytes via sendfile")
	}()

	// Client: read the whole stream, count the bytes.
	conn, err := net.Dial("tcp", ln.Addr().String())
	if err != nil {
		fmt.Println("dial:", err)
		return
	}
	defer conn.Close()
	got, _ := io.Copy(io.Discard, conn)
	fmt.Println("client received", got, "bytes") // client received 1048576 bytes
}

Save the code as main.go and run it:

go run main.go

Expected output:

server sent 1048576 bytes via sendfile
client received 1048576 bytes

The full megabyte moves from file to socket in the kernel. sendfile is used on Linux and macOS; on platforms without it, io.Copy still works through a normal buffer.

💻 Run locally

Copy the code above and run it on your machine

© 2026 ByteLearn.dev. Free courses for developers. · Privacy