Source File
file.go
Belonging Package
os
// Copyright 2009 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.// Package os provides a platform-independent interface to operating system// functionality. The design is Unix-like, although the error handling is// Go-like; failing calls return values of type error rather than error numbers.// Often, more information is available within the error. For example,// if a call that takes a file name fails, such as [Open] or [Stat], the error// will include the failing file name when printed and will be of type// [*PathError], which may be unpacked for more information.//// The os interface is intended to be uniform across all operating systems.// Features not generally available appear in the system-specific package syscall.//// Here is a simple example, opening a file and reading some of it.//// file, err := os.Open("file.go") // For read access.// if err != nil {// log.Fatal(err)// }//// If the open fails, the error string will be self-explanatory, like//// open file.go: no such file or directory//// The file's data can then be read into a slice of bytes. Read and// Write take their byte counts from the length of the argument slice.//// data := make([]byte, 100)// count, err := file.Read(data)// if err != nil {// log.Fatal(err)// }// fmt.Printf("read %d bytes: %q\n", count, data[:count])//// # Concurrency//// The methods of [File] correspond to file system operations. All are// safe for concurrent use. The maximum number of concurrent// operations on a File may be limited by the OS or the system. The// number should be high, but exceeding it may degrade performance or// cause other issues.package osimport ()// Name returns the name of the file as presented to Open.//// It is safe to call Name after [Close].func ( *File) () string { return .name }// Stdin, Stdout, and Stderr are open Files pointing to the standard input,// standard output, and standard error file descriptors.//// Note that the Go runtime writes to standard error for panics and crashes;// closing Stderr may cause those messages to go elsewhere, perhaps// to a file opened later.var (Stdin = NewFile(uintptr(syscall.Stdin), "/dev/stdin")Stdout = NewFile(uintptr(syscall.Stdout), "/dev/stdout")Stderr = NewFile(uintptr(syscall.Stderr), "/dev/stderr"))// Flags to OpenFile wrapping those of the underlying system. Not all// flags may be implemented on a given system.const (// Exactly one of O_RDONLY, O_WRONLY, or O_RDWR must be specified.O_RDONLY int = syscall.O_RDONLY // open the file read-only.O_WRONLY int = syscall.O_WRONLY // open the file write-only.O_RDWR int = syscall.O_RDWR // open the file read-write.// The remaining values may be or'ed in to control behavior.O_APPEND int = syscall.O_APPEND // append data to the file when writing.O_CREATE int = syscall.O_CREAT // create a new file if none exists.O_EXCL int = syscall.O_EXCL // used with O_CREATE, file must not exist.O_SYNC int = syscall.O_SYNC // open for synchronous I/O.O_TRUNC int = syscall.O_TRUNC // truncate regular writable file when opened.)// Seek whence values.//// Deprecated: Use io.SeekStart, io.SeekCurrent, and io.SeekEnd.const (SEEK_SET int = 0 // seek relative to the origin of the fileSEEK_CUR int = 1 // seek relative to the current offsetSEEK_END int = 2 // seek relative to the end)// LinkError records an error during a link or symlink or rename// system call and the paths that caused it.type LinkError struct {Op stringOld stringNew stringErr error}func ( *LinkError) () string {return .Op + " " + .Old + " " + .New + ": " + .Err.Error()}func ( *LinkError) () error {return .Err}// NewFile returns a new [File] with the given file descriptor and name.// The returned value will be nil if fd is not a valid file descriptor.//// NewFile's behavior differs on some platforms://// - On Unix, if fd is in non-blocking mode, NewFile will attempt to return a pollable file.// - On Windows, if fd is opened for asynchronous I/O (that is, [syscall.FILE_FLAG_OVERLAPPED]// has been specified in the [syscall.CreateFile] call), NewFile will attempt to return a pollable// file by associating fd with the Go runtime I/O completion port.// The I/O operations will be performed synchronously if the association fails.//// Only pollable files support [File.SetDeadline], [File.SetReadDeadline], and [File.SetWriteDeadline].//// After passing it to NewFile, fd may become invalid under the same conditions described// in the comments of [File.Fd], and the same constraints apply.func ( uintptr, string) *File {return newFileFromNewFile(, )}// Read reads up to len(b) bytes from the File and stores them in b.// It returns the number of bytes read and any error encountered.// At end of file, Read returns 0, io.EOF.func ( *File) ( []byte) ( int, error) {if := .checkValid("read"); != nil {return 0,}, := .read()return , .wrapErr("read", )}// ReadAt reads len(b) bytes from the File starting at byte offset off.// It returns the number of bytes read and the error, if any.// ReadAt always returns a non-nil error when n < len(b).// At end of file, that error is io.EOF.func ( *File) ( []byte, int64) ( int, error) {if := .checkValid("read"); != nil {return 0,}if < 0 {return 0, &PathError{Op: "readat", Path: .name, Err: errors.New("negative offset")}}for len() > 0 {, := .pread(, )if != nil {= .wrapErr("read", )break}+== [:]+= int64()}return}// ReadFrom implements io.ReaderFrom.func ( *File) ( io.Reader) ( int64, error) {if := .checkValid("write"); != nil {return 0,}, , := .readFrom()if ! {return genericReadFrom(, ) // without wrapping}return , .wrapErr("write", )}// noReadFrom can be embedded alongside another type to// hide the ReadFrom method of that other type.type noReadFrom struct{}// ReadFrom hides another ReadFrom method.// It should never be called.func (noReadFrom) (io.Reader) (int64, error) {panic("can't happen")}// fileWithoutReadFrom implements all the methods of *File other// than ReadFrom. This is used to permit ReadFrom to call io.Copy// without leading to a recursive call to ReadFrom.type fileWithoutReadFrom struct {noReadFrom*File}func genericReadFrom( *File, io.Reader) (int64, error) {return io.Copy(fileWithoutReadFrom{File: }, )}// Write writes len(b) bytes from b to the File.// It returns the number of bytes written and an error, if any.// Write returns a non-nil error when n != len(b).func ( *File) ( []byte) ( int, error) {if := .checkValid("write"); != nil {return 0,}, := .write()if < 0 {= 0}if != len() {= io.ErrShortWrite}epipecheck(, )if != nil {= .wrapErr("write", )}return ,}var errWriteAtInAppendMode = errors.New("os: invalid use of WriteAt on file opened with O_APPEND")// WriteAt writes len(b) bytes to the File starting at byte offset off.// It returns the number of bytes written and an error, if any.// WriteAt returns a non-nil error when n != len(b).//// If file was opened with the [O_APPEND] flag, WriteAt returns an error.func ( *File) ( []byte, int64) ( int, error) {if := .checkValid("write"); != nil {return 0,}if .appendMode {return 0, errWriteAtInAppendMode}if < 0 {return 0, &PathError{Op: "writeat", Path: .name, Err: errors.New("negative offset")}}for len() > 0 {, := .pwrite(, )if != nil {= .wrapErr("write", )break}+== [:]+= int64()}return}// WriteTo implements io.WriterTo.func ( *File) ( io.Writer) ( int64, error) {if := .checkValid("read"); != nil {return 0,}, , := .writeTo()if {return , .wrapErr("read", )}return genericWriteTo(, ) // without wrapping}// noWriteTo can be embedded alongside another type to// hide the WriteTo method of that other type.type noWriteTo struct{}// WriteTo hides another WriteTo method.// It should never be called.func (noWriteTo) (io.Writer) (int64, error) {panic("can't happen")}// fileWithoutWriteTo implements all the methods of *File other// than WriteTo. This is used to permit WriteTo to call io.Copy// without leading to a recursive call to WriteTo.type fileWithoutWriteTo struct {noWriteTo*File}func genericWriteTo( *File, io.Writer) (int64, error) {return io.Copy(, fileWithoutWriteTo{File: })}// 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 ( *File) ( int64, int) ( int64, error) {if := .checkValid("seek"); != nil {return 0,}, := .seek(, )if == nil && .dirinfo.Load() != nil && != 0 {= syscall.EISDIR}if != nil {return 0, .wrapErr("seek", )}return , nil}// WriteString is like Write, but writes the contents of string s rather than// a slice of bytes.func ( *File) ( string) ( int, error) {:= unsafe.Slice(unsafe.StringData(), len())return .Write()}// Mkdir creates a new directory with the specified name and permission// bits (before umask).// If there is an error, it will be of type [*PathError].func ( string, FileMode) error {:= fixLongPath():= ignoringEINTR(func() error {return syscall.Mkdir(, syscallMode())})if != nil {return &PathError{Op: "mkdir", Path: , Err: }}// mkdir(2) itself won't handle the sticky bit on *BSD and Solarisif !supportsCreateWithStickyBit && &ModeSticky != 0 {= setStickyBit()if != nil {Remove()return}}return nil}// setStickyBit adds ModeSticky to the permission bits of path, non atomic.func setStickyBit( string) error {, := Stat()if != nil {return}return Chmod(, .Mode()|ModeSticky)}// Chdir changes the current working directory to the named directory.// If there is an error, it will be of type [*PathError].func ( string) error {if := syscall.Chdir(); != nil {testlog.Open() // observe likely non-existent directoryreturn &PathError{Op: "chdir", Path: , Err: }}if runtime.GOOS == "windows" {:= filepathlite.IsAbs()getwdCache.Lock()if {getwdCache.dir =} else {getwdCache.dir = ""}getwdCache.Unlock()}if := testlog.Logger(); != nil {, := Getwd()if == nil {.Chdir()}}return nil}// Open opens the named file for reading. If successful, methods on// the returned file can be used for reading; the associated file// descriptor has mode [O_RDONLY].// If there is an error, it will be of type [*PathError].func ( string) (*File, error) {return OpenFile(, O_RDONLY, 0)}// Create creates or truncates the named file. If the file already exists,// it is truncated. If the file does not exist, it is created with mode 0o666// (before umask). If successful, methods on the returned File can// be used for I/O; the associated file descriptor has mode [O_RDWR].// The directory containing the file must already exist.// If there is an error, it will be of type [*PathError].func ( string) (*File, error) {return OpenFile(, O_RDWR|O_CREATE|O_TRUNC, 0666)}// OpenFile is the generalized open call; most users will use Open// or Create instead. It opens the named file with specified flag// ([O_RDONLY] etc.). If the file does not exist, and the [O_CREATE] flag// is passed, it is created with mode perm (before umask);// the containing directory must exist. If successful,// methods on the returned File can be used for I/O.// If there is an error, it will be of type [*PathError].func ( string, int, FileMode) (*File, error) {testlog.Open(), := openFileNolog(, , )if != nil {return nil,}.appendMode = &O_APPEND != 0return , nil}var errPathEscapes = errors.New("path escapes from parent")// openDir opens a file which is assumed to be a directory. As such, it skips// the syscalls that make the file descriptor non-blocking as these take time// and will fail on file descriptors for directories.func openDir( string) (*File, error) {testlog.Open()return openDirNolog()}// lstat is overridden in tests.var lstat = Lstat// Rename renames (moves) oldpath to newpath.// If newpath already exists and is not a directory, Rename replaces it.// If newpath already exists and is a directory, Rename returns an error.// OS-specific restrictions may apply when oldpath and newpath are in different directories.// Even within the same directory, on non-Unix platforms Rename is not an atomic operation.// If there is an error, it will be of type *LinkError.func (, string) error {return rename(, )}// Readlink returns the destination of the named symbolic link.// If there is an error, it will be of type [*PathError].//// If the link destination is relative, Readlink returns the relative path// without resolving it to an absolute one.func ( string) (string, error) {return readlink()}// Many functions in package syscall return a count of -1 instead of 0.// Using fixCount(call()) instead of call() corrects the count.func fixCount( int, error) (int, error) {if < 0 {= 0}return ,}// checkWrapErr is the test hook to enable checking unexpected wrapped errors of poll.ErrFileClosing.// It is set to true in the export_test.go for tests (including fuzz tests).var checkWrapErr = false// wrapErr wraps an error that occurred during an operation on an open file.// It passes io.EOF through unchanged, otherwise converts// poll.ErrFileClosing to ErrClosed and wraps the error in a PathError.func ( *File) ( string, error) error {if == nil || == io.EOF {return}if == poll.ErrFileClosing {= ErrClosed} else if checkWrapErr && errors.Is(, poll.ErrFileClosing) {panic("unexpected error wrapping poll.ErrFileClosing: " + .Error())}return &PathError{Op: , Path: .name, Err: }}// TempDir returns the default directory to use for temporary files.//// On Unix systems, it returns $TMPDIR if non-empty, else /tmp.// On Windows, it uses GetTempPath, returning the first non-empty// value from %TMP%, %TEMP%, %USERPROFILE%, or the Windows directory.// On Plan 9, it returns /tmp.//// The directory is neither guaranteed to exist nor have accessible// permissions.func () string {return tempDir()}// UserCacheDir returns the default root directory to use for user-specific// cached data. Users should create their own application-specific subdirectory// within this one and use that.//// On Unix systems, it returns $XDG_CACHE_HOME as specified by// https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html if// non-empty, else $HOME/.cache.// On Darwin, it returns $HOME/Library/Caches.// On Windows, it returns %LocalAppData%.// On Plan 9, it returns $home/lib/cache.//// If the location cannot be determined (for example, $HOME is not defined) or// the path in $XDG_CACHE_HOME is relative, then it will return an error.func () (string, error) {var stringswitch runtime.GOOS {case "windows":= Getenv("LocalAppData")if == "" {return "", errors.New("%LocalAppData% is not defined")}case "darwin", "ios":= Getenv("HOME")if == "" {return "", errors.New("$HOME is not defined")}+= "/Library/Caches"case "plan9":= Getenv("home")if == "" {return "", errors.New("$home is not defined")}+= "/lib/cache"default: // Unix= Getenv("XDG_CACHE_HOME")if == "" {= Getenv("HOME")if == "" {return "", errors.New("neither $XDG_CACHE_HOME nor $HOME are defined")}+= "/.cache"} else if !filepathlite.IsAbs() {return "", errors.New("path in $XDG_CACHE_HOME is relative")}}return , nil}// UserConfigDir returns the default root directory to use for user-specific// configuration data. Users should create their own application-specific// subdirectory within this one and use that.//// On Unix systems, it returns $XDG_CONFIG_HOME as specified by// https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html if// non-empty, else $HOME/.config.// On Darwin, it returns $HOME/Library/Application Support.// On Windows, it returns %AppData%.// On Plan 9, it returns $home/lib.//// If the location cannot be determined (for example, $HOME is not defined) or// the path in $XDG_CONFIG_HOME is relative, then it will return an error.func () (string, error) {var stringswitch runtime.GOOS {case "windows":= Getenv("AppData")if == "" {return "", errors.New("%AppData% is not defined")}case "darwin", "ios":= Getenv("HOME")if == "" {return "", errors.New("$HOME is not defined")}+= "/Library/Application Support"case "plan9":= Getenv("home")if == "" {return "", errors.New("$home is not defined")}+= "/lib"default: // Unix= Getenv("XDG_CONFIG_HOME")if == "" {= Getenv("HOME")if == "" {return "", errors.New("neither $XDG_CONFIG_HOME nor $HOME are defined")}+= "/.config"} else if !filepathlite.IsAbs() {return "", errors.New("path in $XDG_CONFIG_HOME is relative")}}return , nil}// UserHomeDir returns the current user's home directory.//// On Unix, including macOS, it returns the $HOME environment variable.// On Windows, it returns %USERPROFILE%.// On Plan 9, it returns the $home environment variable.//// If the expected variable is not set in the environment, UserHomeDir// returns either a platform-specific default value or a non-nil error.func () (string, error) {, := "HOME", "$HOME"switch runtime.GOOS {case "windows":, = "USERPROFILE", "%userprofile%"case "plan9":, = "home", "$home"}if := Getenv(); != "" {return , nil}// On some operating systems the home directory is not always defined.switch runtime.GOOS {case "android":return "/sdcard", nilcase "ios":return "/", nil}return "", errors.New( + " is not defined")}// Chmod changes the mode of the named file to mode.// If the file is a symbolic link, it changes the mode of the link's target.// If there is an error, it will be of type [*PathError].//// A different subset of the mode bits are used, depending on the// operating system.//// On Unix, the mode's permission bits, [ModeSetuid], [ModeSetgid], and// [ModeSticky] are used.//// On Windows, only the 0o200 bit (owner writable) of mode is used; it// controls whether the file's read-only attribute is set or cleared.// The other bits are currently unused. For compatibility with Go 1.12// and earlier, use a non-zero mode. Use mode 0o400 for a read-only// file and 0o600 for a readable+writable file.//// On Plan 9, the mode's permission bits, [ModeAppend], [ModeExclusive],// and [ModeTemporary] are used.func ( string, FileMode) error { return chmod(, ) }// Chmod changes the mode of the file to mode.// If there is an error, it will be of type [*PathError].func ( *File) ( FileMode) error { return .chmod() }// SetDeadline sets the read and write deadlines for a File.// It is equivalent to calling both SetReadDeadline and SetWriteDeadline.//// Only some kinds of files support setting a deadline. Calls to SetDeadline// for files that do not support deadlines will return ErrNoDeadline.// On most systems ordinary files do not support deadlines, but pipes do.//// A deadline is an absolute time after which I/O operations fail with an// error instead of blocking. The deadline applies to all future and pending// I/O, not just the immediately following call to Read or Write.// After a deadline has been exceeded, the connection can be refreshed// by setting a deadline in the future.//// If the deadline is exceeded a call to Read or Write or to other I/O// methods will return an error that wraps ErrDeadlineExceeded.// This can be tested using errors.Is(err, os.ErrDeadlineExceeded).// That error implements the Timeout method, and calling the Timeout// method will return true, but there are other possible errors for which// the Timeout will return true even if the deadline has not been exceeded.//// An idle timeout can be implemented by repeatedly extending// the deadline after successful Read or Write calls.//// A zero value for t means I/O operations will not time out.func ( *File) ( time.Time) error {return .setDeadline()}// SetReadDeadline sets the deadline for future Read calls and any// currently-blocked Read call.// A zero value for t means Read will not time out.// Not all files support setting deadlines; see SetDeadline.func ( *File) ( time.Time) error {return .setReadDeadline()}// SetWriteDeadline sets the deadline for any future Write calls and any// currently-blocked Write call.// Even if Write times out, it may return n > 0, indicating that// some of the data was successfully written.// A zero value for t means Write will not time out.// Not all files support setting deadlines; see SetDeadline.func ( *File) ( time.Time) error {return .setWriteDeadline()}// SyscallConn returns a raw file.// This implements the syscall.Conn interface.func ( *File) () (syscall.RawConn, error) {if := .checkValid("SyscallConn"); != nil {return nil,}return newRawConn()}// Fd returns the system file descriptor or handle referencing the open file.// If f is closed, the descriptor becomes invalid.// If f is garbage collected, a finalizer may close the descriptor,// making it invalid; see [runtime.SetFinalizer] for more information on when// a finalizer might be run.//// Do not close the returned descriptor; that could cause a later// close of f to close an unrelated descriptor.//// Fd's behavior differs on some platforms://// - On Unix and Windows, [File.SetDeadline] methods will stop working.// - On Windows, the file descriptor will be disassociated from the// Go runtime I/O completion port if there are no concurrent I/O// operations on the file.//// For most uses prefer the f.SyscallConn method.func ( *File) () uintptr {return .fd()}// DirFS returns a file system (an fs.FS) for the tree of files rooted at the directory dir.//// Note that DirFS("/prefix") only guarantees that the Open calls it makes to the// operating system will begin with "/prefix": DirFS("/prefix").Open("file") is the// same as os.Open("/prefix/file"). So if /prefix/file is a symbolic link pointing outside// the /prefix tree, then using DirFS does not stop the access any more than using// os.Open does. Additionally, the root of the fs.FS returned for a relative path,// DirFS("prefix"), will be affected by later calls to Chdir. DirFS is therefore not// a general substitute for a chroot-style security mechanism when the directory tree// contains arbitrary content.//// Use [Root.FS] to obtain a fs.FS that prevents escapes from the tree via symbolic links.//// The directory dir must not be "".//// The result implements [io/fs.StatFS], [io/fs.ReadFileFS], [io/fs.ReadDirFS], and// [io/fs.ReadLinkFS].func ( string) fs.FS {return dirFS()}var _ fs.StatFS = dirFS("")var _ fs.ReadFileFS = dirFS("")var _ fs.ReadDirFS = dirFS("")var _ fs.ReadLinkFS = dirFS("")type dirFS stringfunc ( dirFS) ( string) (fs.File, error) {, := .join()if != nil {return nil, &PathError{Op: "open", Path: , Err: }}, := Open()if != nil {// DirFS takes a string appropriate for GOOS,// while the name argument here is always slash separated.// dir.join will have mixed the two; undo that for// error reporting..(*PathError).Path =return nil,}return , nil}// The ReadFile method calls the [ReadFile] function for the file// with the given name in the directory. The function provides// robust handling for small files and special file systems.// Through this method, dirFS implements [io/fs.ReadFileFS].func ( dirFS) ( string) ([]byte, error) {, := .join()if != nil {return nil, &PathError{Op: "readfile", Path: , Err: }}, := ReadFile()if != nil {if , := .(*PathError); {// See comment in dirFS.Open..Path =}return nil,}return , nil}// ReadDir reads the named directory, returning all its directory entries sorted// by filename. Through this method, dirFS implements [io/fs.ReadDirFS].func ( dirFS) ( string) ([]DirEntry, error) {, := .join()if != nil {return nil, &PathError{Op: "readdir", Path: , Err: }}, := ReadDir()if != nil {if , := .(*PathError); {// See comment in dirFS.Open..Path =}return nil,}return , nil}func ( dirFS) ( string) (fs.FileInfo, error) {, := .join()if != nil {return nil, &PathError{Op: "stat", Path: , Err: }}, := Stat()if != nil {// See comment in dirFS.Open..(*PathError).Path =return nil,}return , nil}func ( dirFS) ( string) (fs.FileInfo, error) {, := .join()if != nil {return nil, &PathError{Op: "lstat", Path: , Err: }}, := Lstat()if != nil {// See comment in dirFS.Open..(*PathError).Path =return nil,}return , nil}func ( dirFS) ( string) (string, error) {, := .join()if != nil {return "", &PathError{Op: "readlink", Path: , Err: }}return Readlink()}// join returns the path for name in dir.func ( dirFS) ( string) (string, error) {if == "" {return "", errors.New("os: DirFS with empty root")}, := filepathlite.Localize()if != nil {return "", ErrInvalid}if IsPathSeparator([len()-1]) {return string() + , nil}return string() + string(PathSeparator) + , nil}// ReadFile reads the named file and returns the contents.// A successful call returns err == nil, not err == EOF.// Because ReadFile reads the whole file, it does not treat an EOF from Read// as an error to be reported.func ( string) ([]byte, error) {, := Open()if != nil {return nil,}defer .Close()return readFileContents(statOrZero(), .Read)}func statOrZero( *File) int64 {if , := .Stat(); == nil {return .Size()}return 0}// readFileContents reads the contents of a file using the provided read function// (*os.File.Read, except in tests) one or more times, until an error is seen.//// The provided size is the stat size of the file, which might be 0 for a// /proc-like file that doesn't report a size.func readFileContents( int64, func([]byte) (int, error)) ([]byte, error) {:= == 0// Figure out how big to make the initial slice. For files with known size// that fit in memory, use that size + 1. Otherwise, use a small buffer and// we'll grow.var intif int64(int()) == {= int()}++ // one byte for final read at EOFconst = 512// If a file claims a small size, read at least 512 bytes. In particular,// files in Linux's /proc claim size 0 but then do not work right if read in// small pieces, so an initial read of 1 byte would not work correctly.if < {=}:= make([]byte, 0, )for {, := ([len():cap()])= [:len()+]if != nil {if == io.EOF {= nil}return ,}// If we're either out of capacity or if the file was a /proc-like zero// sized file, grow the buffer. Per Issue 72080, we always want to issue// Read calls on zero-length files with a non-tiny buffer size.:= cap() - len()if == 0 || ( && < ) {= slices.Grow(, )}}}// WriteFile writes data to the named file, creating it if necessary.// If the file does not exist, WriteFile creates it with permissions perm (before umask);// otherwise WriteFile truncates it before writing, without changing permissions.// Since WriteFile requires multiple system calls to complete, a failure mid-operation// can leave the file in a partially written state.func ( string, []byte, FileMode) error {, := OpenFile(, O_WRONLY|O_CREATE|O_TRUNC, )if != nil {return}_, = .Write()if := .Close(); != nil && == nil {=}return}
![]() |
The pages are generated with Golds v0.7.9-preview. (GOOS=linux GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds. |