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 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率
  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!
  • ¥15 drone 推送镜像时候 purge: true 推送完毕后没有删除对应的镜像,手动拷贝到服务器执行结果正确在样才能让指令自动执行成功删除对应镜像,如何解决?
  • ¥15 求daily translation(DT)偏差订正方法的代码
  • ¥15 js调用html页面需要隐藏某个按钮