func(f *File) Write(b []byte) (n int, err error) { if err := f.checkValid("write"); err != nil { return0, err } n, e := f.write(b) if n < 0 { n = 0 } if n != len(b) { err = io.ErrShortWrite }
epipecheck(f, e)
if e != nil { err = &PathError{"write", f.name, e} } return n, err }
接下来,我们写一段例子来实现它。
1 2 3 4 5 6 7 8 9 10
funcmain() { f, err := os.OpenFile("test.txt",os.O_RDWR|os.O_CREATE|os.O_APPEND,os.ModePerm) if(err!=nil){ fmt.Println(err) } f.Write([]byte(string("hello mama miya"))) fmt.Println(f) } result: 创建了一个test.txt,并成功将hello mama miya写入
注意的是,在Write内部,还调用了writes这个私有方法。
1 2 3 4 5 6 7 8 9 10
// write writes len(b) bytes to the File. // It returns the number of bytes written and an error, if any. func(f *File) write(b []byte) (n int, err error) { f.l.Lock() defer f.l.Unlock() if f.isConsole { return f.writeConsole(b) } return fixCount(syscall.Write(f.fd, b)) }
虽然已经超出了io包的范畴,不过也可以简单得说下。 *File也是一个结构
1 2 3 4 5 6 7 8 9 10 11 12 13
type file struct { fd syscall.Handle name string dirinfo *dirInfo // nil unless directory being read l sync.Mutex // used to implement windows pread/pwrite
// only for console io isConsole bool lastbits []byte// first few bytes of the last incomplete rune in last write readuint16 []uint16// buffer to hold uint16s obtained with ReadConsole readbyte []byte// buffer to hold decoding of readuint16 from utf16 to utf8 readbyteOffset int// readbyte[readOffset:] is yet to be consumed with file.Read }
// Seek sets the offset for the next Read or Write on file to offset, interpreted // according to whence: 0 means relative to the origin of the file, 1 means // relative to the current offset, and 2 means relative to the end. // It returns the new offset and an error, if any. // The behavior of Seek on a file opened with O_APPEND is not specified. func(f *File) Seek(offset int64, whence int) (ret int64, err error) { if err := f.checkValid("seek"); err != nil { return0, err } r, e := f.seek(offset, whence) if e == nil && f.dirinfo != nil && r != 0 { e = syscall.EISDIR } if e != nil { return0, &PathError{"seek", f.name, e} } return r, nil }
// Seek whence values. const ( SeekStart = 0// seek relative to the origin of the file SeekCurrent = 1// seek relative to the current offset SeekEnd = 2// seek relative to the end )
其实在file.go里面也有定义
1 2 3 4 5 6
// Deprecated: Use io.SeekStart, io.SeekCurrent, and io.SeekEnd. const ( SEEK_SET int = 0// seek relative to the origin of the file SEEK_CUR int = 1// seek relative to the current offset SEEK_END int = 2// seek relative to the end )