drdyszuy488152 2018-10-08 07:21
浏览 697
已采纳

在golang中将[] byte变成“虚拟”文件对象的简单方法?

I know there are Go libraries that create entire filesystems like VFS. But I only want to make a byte array into something that can fulfil the File interface.

  • 写回答

2条回答 默认 最新

  • douzhan8395 2018-10-08 08:05
    关注

    There is no ready solution for this in the standard library, but it's not that hard to do it yourself.

    What we need is this http.File interface:

    type File interface {
            io.Closer
            io.Reader
            io.Seeker
            Readdir(count int) ([]os.FileInfo, error)
            Stat() (os.FileInfo, error)
    }
    

    Please note that we can utilize bytes.Reader to do the heavy task, as that alone implements io.Reader and io.Seeker. io.Closer can be a noop, and Readdir() may return nil, nil as we're mocking a file not a directory, its Readdir() won't even be called.

    The "hardest" part is to mock Stat() to return a value that implements os.FileInfo.

    Here's a simple mocked FileInfo:

    type myFileInfo struct {
        name string
        data []byte
    }
    
    func (mif myFileInfo) Name() string       { return mif.name }
    func (mif myFileInfo) Size() int64        { return int64(len(mif.data)) }
    func (mif myFileInfo) Mode() os.FileMode  { return 0444 }        // Read for all
    func (mif myFileInfo) ModTime() time.Time { return time.Time{} } // Return anything
    func (mif myFileInfo) IsDir() bool        { return false }
    func (mif myFileInfo) Sys() interface{}   { return nil }
    

    And with that we have everything to create our mocked http.File:

    type MyFile struct {
        *bytes.Reader
        mif myFileInfo
    }
    
    func (mf *MyFile) Close() error { return nil } // Noop, nothing to do
    
    func (mf *MyFile) Readdir(count int) ([]os.FileInfo, error) {
        return nil, nil // We are not a directory but a single file
    }
    
    func (mf *MyFile) Stat() (os.FileInfo, error) {
        return mf.mif, nil
    }
    

    Example using it (try it on the Go Playground):

    data := []byte{0, 1, 2, 3}
    
    mf := &MyFile{
        Reader: bytes.NewReader(data),
        mif: myFileInfo{
            name: "somename.txt",
            data: data,
        },
    }
    
    var f http.File = mf
    _ = f
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 有赏,i卡绘世画不出
  • ¥15 如何用stata画出文献中常见的安慰剂检验图
  • ¥15 c语言链表结构体数据插入
  • ¥40 使用MATLAB解答线性代数问题
  • ¥15 COCOS的问题COCOS的问题
  • ¥15 FPGA-SRIO初始化失败
  • ¥15 MapReduce实现倒排索引失败
  • ¥15 ZABBIX6.0L连接数据库报错,如何解决?(操作系统-centos)
  • ¥15 找一位技术过硬的游戏pj程序员
  • ¥15 matlab生成电测深三层曲线模型代码