func (d *DirectIO) Write(p []byte) (nn int, err error) {
	for len(p) >= d.Available() && d.err == nil {
		var n int
		if d.Buffered() == 0 && align(p) == 0 {
			if (len(p) % blockSize) == 0 {
				n, d.err = d.f.Write(p)
			} else {
				l := len(p) & -blockSize
				var nl int
				nl, d.err = d.f.Write(p[:l])
				n = copy(d.buf[d.n:], p[l:])
				d.n += n
				n += nl
			}
		} else {
			n = copy(d.buf[d.n:], p)
			d.n += n
			d.flush()
		}
		nn += n
		p = p[n:]
	}
	if d.err != nil {
		return nn, d.err
	}
	n := copy(d.buf[d.n:], p)
	d.n += n
	nn += n
	return nn, nil
}
Write writes the contents of p into the buffer.
It returns the number of bytes written.
If nn < len(p), it also returns an error explaining
why the write is short.
package directio
import (
	"errors"
	"io"
	"os"
	"unsafe"
)
const (
	blockSize = 512
	defaultBufSize = 8192
)
func align(b []byte) int {
	return int(uintptr(unsafe.Pointer(&b[0])) & uintptr(blockSize-1))
}
func allocAlignedBuf(n int) ([]byte, error) {
	if n == 0 {
		return nil, errors.New("size is `0` can't allocate buffer")
	}
	buf := make([]byte, n+blockSize)
	a1 := align(buf)
	offset := 0
	if a1 != 0 {
		offset = blockSize - a1
	}
	buf = buf[offset : offset+n]
	if a1 == 0 {
		return buf, nil
	}
	a2 := align(buf)
	if a2 != 0 {
		return nil, errors.New("can't allocate aligned buffer")
	}
	return buf, nil
}
type DirectIO struct {
	f   *os.File
	buf []byte
	n   int
	err error
}
func NewSize(f *os.File, size int) (*DirectIO, error) {
	if err := checkDirectIO(f.Fd()); err != nil {
		return nil, err
	}
	if size%blockSize != 0 {
		size = size & -blockSize
	}
	if size < defaultBufSize {
		size = defaultBufSize
	}
	buf, err := allocAlignedBuf(size)
	if err != nil {
		return nil, err
	}
	return &DirectIO{
		buf: buf,
		f:   f,
	}, nil
}
func New(f *os.File) (*DirectIO, error) {
	return NewSize(f, defaultBufSize)
}
func (d *DirectIO) flush() error {
	if d.err != nil {
		return d.err
	}
	if d.n == 0 {
		return nil
	}
	n, err := d.f.Write(d.buf[0:d.n])
	if n < d.n && err == nil {
		err = io.ErrShortWrite
	}
	if err != nil {
		if n > 0 && n < d.n {
			copy(d.buf[0:d.n-n], d.buf[n:d.n])
		}
	}
	d.n -= n
	return err
}
func (d *DirectIO) Flush() error {
	fd := d.f.Fd()
	err := setDirectIO(fd, false)
	if err != nil {
		return err
	}
	err = d.flush()
	if err != nil {
		return err
	}
	return setDirectIO(fd, true)
}
func (d *DirectIO) Available() int { return len(d.buf) - d.n }
func (d *DirectIO) Buffered() int { return d.n }