doubao6936 2019-01-20 11:58
浏览 318

Golang将自定义os.File添加到os.Stdout

I'm trying to write output to a file whenever I print something to the console. There didn't seem to be any nice examples out there using a continuous stream, but rather reading a single value so I came up with the following code:

package main

import (
    "fmt"
    "io"
    "os"
)

type ahhh struct {
    *os.File
    __writer io.Writer
}

func (me *ahhh) Write(b []byte) (n int, err error) {
    return me.__writer.Write(b)
}

func write_print_to_file(file_name string) {
    file, _ := os.OpenFile(file_name, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)

    new_stdout := &ahhh{file, io.MultiWriter(file, os.Stdout)}

    os.Stdout = new_stdout
}

func main() {
    write_print_to_file("output.log")
    fmt.Println("Hello world!")
}

For some reason os.Stdout = new_stdout doesn't want to work. I'm fairly certain this should be an allowed assignment as I use something of similar structure in my FUSE file system, so I'm curious why os.Stdout doesn't want to accept my inherited os.File.

Alternatively if this really isn't possible any good suggestions for making a continuous data stream to a file?

  • 写回答

1条回答 默认 最新

  • dongxiao0449 2019-01-20 12:04
    关注
    $ go doc os.stdout
    var (
      Stdin  = NewFile(uintptr(syscall.Stdin), "/dev/stdin")
      Stdout = NewFile(uintptr(syscall.Stdout), "/dev/stdout")
      Stderr = NewFile(uintptr(syscall.Stderr), "/dev/stderr")
    )
        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.
    

    $ go doc os.newfile
    func NewFile(fd uintptr, name string) *File
        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. On Unix
        systems, if the file descriptor is in non-blocking mode, NewFile will
        attempt to return a pollable File (one for which the SetDeadline methods
        work).
    

    $ go doc -u os.file
    type File struct {
      *file // os specific
    }
        File represents an open file descriptor.
    
    func Create(name string) (*File, error)
    func NewFile(fd uintptr, name string) *File
    func Open(name string) (*File, error)
    func OpenFile(name string, flag int, perm FileMode) (*File, error)
    func newFile(fd uintptr, name string, kind newFileKind) *File
    func openFdAt(fd int, path string) (*File, error)
    func openFileNolog(name string, flag int, perm FileMode) (*File, error)
    func (f *File) Chdir() error
    func (f *File) Chmod(mode FileMode) error
    func (f *File) Chown(uid, gid int) error
    func (f *File) Close() error
    func (f *File) Fd() uintptr
    func (f *File) Name() string
    func (f *File) Read(b []byte) (n int, err error)
    func (f *File) ReadAt(b []byte, off int64) (n int, err error)
    func (f *File) Readdir(n int) ([]FileInfo, error)
    func (f *File) Readdirnames(n int) (names []string, err error)
    func (f *File) Seek(offset int64, whence int) (ret int64, err error)
    func (f *File) SetDeadline(t time.Time) error
    func (f *File) SetReadDeadline(t time.Time) error
    func (f *File) SetWriteDeadline(t time.Time) error
    func (f *File) Stat() (FileInfo, error)
    func (f *File) Sync() error
    func (f *File) SyscallConn() (syscall.RawConn, error)
    func (f *File) Truncate(size int64) error
    func (f *File) Write(b []byte) (n int, err error)
    func (f *File) WriteAt(b []byte, off int64) (n int, err error)
    func (f *File) WriteString(s string) (n int, err error)
    func (f *File) checkValid(op string) error
    func (f *File) chmod(mode FileMode) error
    func (file File) close() error
    func (f *File) pread(b []byte, off int64) (n int, err error)
    func (f *File) pwrite(b []byte, off int64) (n int, err error)
    func (f *File) read(b []byte) (n int, err error)
    func (f *File) readdir(n int) (fi []FileInfo, err error)
    func (f *File) readdirnames(n int) (names []string, err error)
    func (f *File) seek(offset int64, whence int) (ret int64, err error)
    func (f *File) setDeadline(t time.Time) error
    func (f *File) setReadDeadline(t time.Time) error
    func (f *File) setWriteDeadline(t time.Time) error
    func (f *File) wrapErr(op string, err error) error
    func (f *File) write(b []byte) (n int, err error)
    type file struct {
      pfd         poll.FD
      name        string
      dirinfo     *dirInfo // nil unless directory being read
      nonblock    bool     // whether we set nonblocking mode
      stdoutOrErr bool     // whether this is stdout or stderr
    }
        file is the real representation of *File. The extra level of indirection
        ensures that no clients of os can overwrite this data, which could cause the
        finalizer to close the wrong file descriptor.
    
    func (file *file) close() error
    

    I'm fairly certain this should be an allowed assignment.

    new_stdout := &ahhh{file, io.MultiWriter(file, os.Stdout)}
    os.Stdout = new_stdout
    

    Is it an *os.File? No. Why should it be allowed?

    评论

报告相同问题?

悬赏问题

  • ¥50 导入文件到网吧的电脑并且在重启之后不会被恢复
  • ¥15 (希望可以解决问题)ma和mb文件无法正常打开,打开后是空白,但是有正常内存占用,但可以在打开Maya应用程序后打开场景ma和mb格式。
  • ¥20 ML307A在使用AT命令连接EMQX平台的MQTT时被拒绝
  • ¥20 腾讯企业邮箱邮件可以恢复么
  • ¥15 有人知道怎么将自己的迁移策略布到edgecloudsim上使用吗?
  • ¥15 错误 LNK2001 无法解析的外部符号
  • ¥50 安装pyaudiokits失败
  • ¥15 计组这些题应该咋做呀
  • ¥60 更换迈创SOL6M4AE卡的时候,驱动要重新装才能使用,怎么解决?
  • ¥15 让node服务器有自动加载文件的功能