You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: holes.go
    path of file: ./repos/gocryptfs/contrib/findholes/holes
    
    the code of the file until where you have to start completion: // Package holes finds and pretty-prints holes & data sections of a file.
// Used by TestFileHoleCopy in the gocryptfs test suite.
package holes

import (
	"fmt"
	"log"
	"math/rand"
	"os"
	"syscall"
	"time"
)

const (
	SEEK_DATA = 3
	SEEK_HOLE = 4

	SegmentHole = SegmentType(100)
	SegmentData = SegmentType(101)
	SegmentEOF  = SegmentType(102)
)

type Whence int

func (w Whence) String() string {
	switch w {
	case SEEK_DATA:
		return "SEEK_DATA"
	case SEEK_HOLE:
		return "SEEK_HOLE"
	default:
		return "???"
	}
}

type Segment struct {
	Offset int64
	Type   SegmentType
}

func (s Segment) String() string {
	return fmt.Sprintf("%10d %v", s.Offset, s.Type)
}

type SegmentType int

func (s SegmentType) String() string {
	s
    
func Find(fd int) (segments []Segment, err error) {
	var st syscall.Stat_t
	err = syscall.Fstat(fd, &st)
	if err != nil {
		return nil, err
	}
	totalSize := st.Size

	var cursor int64

	// find out if file starts with data or hole
	off, err := syscall.Seek(fd, 0, SEEK_DATA)
	// starts with hole and has no data
	if err == syscall.ENXIO {
		segments = append(segments,
			Segment{0, SegmentHole},
			Segment{totalSize, SegmentEOF})
		return segments, nil
	}
	if err != nil {
		return nil, err
	}
	// starts with data
	if off == cursor {
		segments = append(segments, Segment{0, SegmentData})
	} else {
		// starts with hole
		segments = append(segments,
			Segment{0, SegmentHole},
			Segment{off, SegmentData})
		cursor = off
	}

	// now we are at the start of data.
	// find next hole, then next data, then next hole, then next data...
	for {
		oldCursor := cursor
		// Next hole
		off, err = syscall.Seek(fd, cursor, SEEK_HOLE)
		if err != nil {
			return nil, err
		}
		segments = append(segments, Segment{off, SegmentHole})
		cursor = off

		// Next data
		off, err := syscall.Seek(fd, cursor, SEEK_DATA)
		// No more data?
		if err == syscall.ENXIO {
			segments = append(segments,
				Segment{totalSize, SegmentEOF})
			break
		}
		if err != nil {
			return nil, err
		}
		segments = append(segments, Segment{off, SegmentData})
		cursor = off

		if oldCursor == cursor {
			return nil, fmt.Errorf("%s\nerror: seek loop!", PrettyPrint(segments))
		}
	}
	return segments, nil
}