func (p *NvidiaPCILib) Devices() ([]*PCIDevice, error) {
	deviceDirs, err := ioutil.ReadDir(PciDevicesRoot)
	if err != nil {
		return nil, fmt.Errorf("Unable to read PCI bus devices: %v", err)
	}
	var devices []*PCIDevice
	for _, deviceDir := range deviceDirs {
		devicePath := path.Join(PciDevicesRoot, deviceDir.Name())
		address := deviceDir.Name()
		vendor, err := ioutil.ReadFile(path.Join(devicePath, "vendor"))
		if err != nil {
			return nil, fmt.Errorf("Unable to read PCI device vendor id for %s: %v", address, err)
		}
		if strings.TrimSpace(string(vendor)) != PciNvidiaVendorID {
			continue
		}
		class, err := ioutil.ReadFile(path.Join(devicePath, "class"))
		if err != nil {
			return nil, fmt.Errorf("Unable to read PCI device class for %s: %v", address, err)
		}
		config, err := ioutil.ReadFile(path.Join(devicePath, "config"))
		if err != nil {
			return nil, fmt.Errorf("Unable to read PCI configuration space for %s: %v", address, err)
		}
		device := &PCIDevice{
			Path:    devicePath,
			Address: address,
			Vendor:  strings.TrimSpace(string(vendor)),
			Class:   string(class)[0:4],
			Config:  config,
		}
		devices = append(devices, device)
	}
	return devices, nil
}
Devices returns all PCI devices on the system
package main
import (
	"fmt"
	"io/ioutil"
	"path"
	"strings"
)
type NvidiaPCI interface {
	Devices() ([]*PCIDevice, error)
}
type PCIDevice struct {
	Path    string
	Address string
	Class   string
	Vendor  string
	Config  []byte
}
const (
	PciDevicesRoot = "/sys/bus/pci/devices"
	PciStatusByte = 0x06
	PciStatusCapabilityList = 0x10
	PciCapabilityList = 0x34
	PciCapabilityListID = 0
	PciCapabilityListNext = 1
	PciCapabilityLength = 2
	PciCapabilityVendorSpecificID = 0x09
	PciNvidiaVendorID = "0x10de"
)
type NvidiaPCILib struct{}
func NewNvidiaPCILib() NvidiaPCI {
	return &NvidiaPCILib{}
}