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: iter.go
    path of file: ./repos/kubeedge/vendor/github.com/cilium/ebpf/link
    
    the code of the file until where you have to start completion: package link

import (
	"fmt"
	"io"
	"unsafe"

	"github.com/cilium/ebpf"
	"github.com/cilium/ebpf/internal/sys"
)

type IterOptions struct {
	// Program must be of type Tracing with attach type
	// AttachTraceIter. The kind of iterator to attach to is
	// determined at load time via the AttachTo field.
	//
	// AttachTo requires the kernel to include BTF of itself,
	// and it to be compiled with a recent pahole (>= 1.16).
	Program *ebpf.Program

	// Map specifies the target map for bpf_map_elem and sockmap iterators.
	// It may be nil.
	Map *ebpf.Map
}

// AttachIter attaches a BPF seq_file iterator.
func AttachIter(opts IterOptions) (*Iter, error) {
	if err := haveBPFLink(); err != nil {
		return nil, err
	}

	progFd := opts.Program.FD()
	if
    
func AttachIter(opts IterOptions) (*Iter, error) {
	if err := haveBPFLink(); err != nil {
		return nil, err
	}

	progFd := opts.Program.FD()
	if progFd < 0 {
		return nil, fmt.Errorf("invalid program: %s", sys.ErrClosedFd)
	}

	var info bpfIterLinkInfoMap
	if opts.Map != nil {
		mapFd := opts.Map.FD()
		if mapFd < 0 {
			return nil, fmt.Errorf("invalid map: %w", sys.ErrClosedFd)
		}
		info.map_fd = uint32(mapFd)
	}

	attr := sys.LinkCreateIterAttr{
		ProgFd:      uint32(progFd),
		AttachType:  sys.AttachType(ebpf.AttachTraceIter),
		IterInfo:    sys.NewPointer(unsafe.Pointer(&info)),
		IterInfoLen: uint32(unsafe.Sizeof(info)),
	}

	fd, err := sys.LinkCreateIter(&attr)
	if err != nil {
		return nil, fmt.Errorf("can't link iterator: %w", err)
	}

	return &Iter{RawLink{fd, ""}}, err
}