MCPcopy Index your code
hub / github.com/beyondstorage/go-storage

github.com/beyondstorage/go-storage @v5.0.0

Chat with this repo
repository ↗ · DeepWiki ↗ · release v5.0.0 ↗ · + Follow
884 symbols 1,970 edges 75 files 342 documented · 39%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

go-storage

网站 | 文档 | 社区

Build Status Go dev License go storage dev

一个厂商中立的存储库。

愿景

只需一次编写,即可在任意存储服务中运行。

目标

  • 厂商中立
  • 生产就绪
  • 极致性能

示例

package main

import (
    "log"

    "go.beyondstorage.io/v5/services"
    "go.beyondstorage.io/v5/types"

    // 添加 fs 支持
    _ "github.com/beyondstorage/go-service-fs/v3"
    // 添加 s3 支持
    _ "github.com/beyondstorage/go-service-s3/v2"
    // 添加 gcs 支持
    _ "github.com/beyondstorage/go-service-gcs/v2"
    // 添加 azblob 支持
    _ "github.com/beyondstorage/go-service-azblob/v2"
    // 更多支持,可在 BeyondStorage 下获取
    _ "github.com/beyondstorage/go-service-xxx" 
)

func main() {
    // 使用连接字符串初始化 storager
    store, err := services.NewStoragerFromString("s3://bucket_name/path/to/workdir")
    if err != nil {
        log.Fatalf("service init failed: %v", err)
    }

    // 将 io.Reader 中的数据写入 hello.txt
    n, err := store.Write("hello.txt", r, length)

    // 从 hello.txt 中读取数据到 io.Writer
    n, err := store.Read("hello.txt", w)

    // 检查 hello.txt 是否存在并获取其元数据
    o, err := store.Stat("hello.txt")

    // 使用对象的函数获取元数据
    length, ok := o.GetContentLength()

    // List 将创建路径下对象的迭代器
    it, err := store.List("path")

    for {
        // 使用迭代器检索下一个对象,直到迭代完成
        o, err := it.Next()
        if errors.Is(err, types.IteraoorDone) {
            break
        }
    }

    // 删除 hello.txt
    err = store.Delete("hello.txt")
}

更多示例可以在 go-storage-example 找到。

特点

支持多种本地服务

目前已经有 16 个稳定的服务通过了所有的 集成测试

另有 3 个公测版本的服务已实现了所需功能,但还没有通过 集成测试

最后还有 4 个处于内测阶段的服务仍在开发中。

更多关于服务的想法可以在 Service Integration Tracking 找到。

完整且易扩展的接口

基本操作

  • 元数据: 获取 storager 元数据
meta := store.Metadata()
_ := meta.GetWorkDir() // 获取对象的工作目录
_, ok := meta.GetWriteSizeMaximum() // 获取写操作的最大尺寸
  • 读取: 读取 对象 的内容
// 在偏移量 1024 处读取 2048 字节到 io.Writer
n, err := store.Read("path", w, pairs.WithOffset(1024), pairs.WithSize(2048))
  • 写入: 将内容写入 对象
// 从 io.Reader 写入 2048 字节
n, err := store.Write("path", r, 2048)
  • 统计: 获取 对象 元数据并检查是否存在
o, err := store.Stat("path")
if errors.Is(err, services.ErrObjectNotExist) {
    // 对象不存在
}
length, ok := o.GetContentLength() // 获取对象的内容长度
  • 删除: 删除一个 对象
err := store.Delete("path") // 删除对象 "路径"
  • 列表: 列出给定前缀或目录中的 对象
it, err := store.List("path")
for {
    o, err := it.Next()
    if err != nil && errors.Is(err, types.IteratorDone) {
        // 列表结束
    }
    length, ok := o.GetContentLength() // 获取对象的内容长度
}

扩展操作

  • 拷贝: 复制一个 对象 到 storager
err := store.(Copier).Copy(src, dst) // 从 src 复制一个对象到 dst
  • 移动: 移动一个 对象 到 storager
err := store.(Mover).Move(src, dst) // 从 src 移动一个对象到 dst
  • 链接: 为 对象 生成一个可访问的公共 url
url, err := store.(Reacher).Reach("path") // 生成一个对象的 url
  • 目录: 对象 目录
o, err := store.(Direr).CreateDir("path") // 创建一个对象目录

大文件操作

  • 分段: 允许进行分段上传
ms := store.(Multiparter)

// 创建一个分段对象
o, err := ms.CreateMultipart("path")
// 将 io.reader 中的 1024 字节分段写入索引 1
n, part, err := ms.WriteMultipart(o, r, 1024, 1)
// 完成分段对象创建
err := ms.CompleteMultipart(o, []*Part{part})
  • 追加: 允许追加到一个对象上
as := store.(Appender)

// 创建一个可追加的对象
o, err := as.CreateAppend("path")
// 从 io.Reader 写入 1024 字节
n, err := as.WriteAppend(o, r, 1024)
// 提交一个待追加的对象
err = as.CommitAppend(o)
  • 块: 允许将一个对象与块 id 进行组合
bs := store.(Blocker)

// 创建一个块对象
o, err := bs.CreateBlock("path")
// 将 io.reader 中的 1024 字节写入 id 为 ”id-abc“ 的块
n, err := bs.WriteBlock(o, r, 1024, "id-abc")
// 通过块 id 组合区块
err := bs.CombineBlock(o, []string{"id-abc"})
  • 页:允许进行随机写入
ps := store.(Pager)

// 创建一个页面对象
o, err := ps.CreatePage("path")
// Write 1024 bytes from io.Reader at offset 2048
n, err := ps.WritePage(o, r, 1024, 2048)

综合元数据

全局对象元数据

  • id: 服务中的唯一键
  • name: 服务工作目录的相对路径
  • mode: 对象的模式可以由以下几种进行组合:read, dir, part 以及 更多
  • etag: 实体标签,定义于 rfc2616
  • content-length: 对象的内容大小
  • content-md5: rfc2616 中定义的 Md5 简介
  • content-type: rfc2616 中定义的媒体类型
  • last-modified: 对象的最后更新时间

系统对象元数据

服务系统对象元数据,如 storage-class 等。

o, err := store.Stat("path")

// 通过 go-service-s3 提供的 API 获取服务系统元数据
om := s3.GetObjectSystemMetadata(o)
_ = om.StorageClass // 此对象的存储类型
_ = om.ServerSideEncryptionCustomerAlgorithm // 此对象的 sse 算法

强类型的接口

自我维护的代码生成器 定义 有助于生成我们所有的 API、pairs 和元数据。

生成的 pairs 可用作 API 的可选参数。

func WithContentMd5(v string) Pair {
    return Pair{
        Key:   "content_md5",
        Value: v,
    }
}

生成的对象元数据可用于从对象中获取内容 md5。

func (o *Object) GetContentMd5() (string, bool) {
    o.stat()

    if o.bit&objectIndexContentMd5 != 0 {
        return o.contentMd5, true
    }

    return "", false
}

服务器端加密

支持通过 system pair 和 system metadata 指定在服务端对数据进行加密编码, 并且我们可以通过 Default Pairs 来简化工作。


func NewS3SseC(key []byte) (types.Storager, error) {
    defaultPairs := s3.DefaultStoragePairs{
        Write: []types.Pair{
            // 要求密钥的加密算法必须为 AES256
            s3.WithServerSideEncryptionCustomerAlgorithm(s3.ServerSideEncryptionAes256),
            // 你的 AES-256 密钥, 必须具有 32 个字节长度
            s3.WithServerSideEncryptionCustomerKey(key),
        },
        // 现在你必须提供客户密钥才能读取加密数据
        Read: []types.Pair{
            // 要求密钥的加密算法必须为 AES256
            s3.WithServerSideEncryptionCustomerAlgorithm(s3.ServerSideEncryptionAes256),
            // 你的 AES-256 密钥, 必须具有 32 个字节长度
            s3.WithServerSideEncryptionCustomerKey(key),
        }}

    return s3.NewStorager(..., s3.WithDefaultStoragePairs(defaultPairs))
}

赞助商

Extension points exported contracts — how you extend this code

InternalError (Interface)
(no doc) [8 implementers]
services/error.go
ReadAtCloser (Interface)
ReadAtCloser is the composition of io.Closer and io.ReaderAt
pkg/iowrap/interface.go
NewServicerFunc (FuncType)
NewServicerFunc is a function that can initiate a new servicer.
services/new.go
Copier (Interface)
(no doc) [1 implementers]
docs/rfcs/1/main_test.go
Interceptor (FuncType)
(no doc)
types/interceptor.go
NewStoragerFunc (FuncType)
NewStoragerFunc is a function that can initiate a new storager.
services/new.go
TestStorager2 (Interface)
(no doc) [1 implementers]
docs/rfcs/1/main_test.go
TestStorager3 (Interface)
(no doc) [1 implementers]
docs/rfcs/1/main_test.go

Core symbols most depended-on inside this repo

Error
called by 102
types/error.go
NewOperationNotImplementedError
called by 70
types/error.go
NewRand
called by 41
pkg/randbytes/randbytes.go
DisplayName
called by 25
cmd/definitions/type.go
stat
called by 20
types/object.go
formatError
called by 16
cmd/definitions/tests/utils.go
TypeName
called by 14
cmd/definitions/type.go
ParsedParams
called by 13
cmd/definitions/type.go

Shape

Method 539
Function 192
Struct 122
Interface 22
FuncType 7
TypeAlias 2

Languages

Go100%

Modules by API surface

types/operation.generated.go216 symbols
cmd/definitions/tests/generated.go111 symbols
types/info.generated.go41 symbols
cmd/definitions/type.go41 symbols
types/object.generated.go38 symbols
services/error.go35 symbols
cmd/definitions/bindata/bindata.go34 symbols
pkg/iowrap/mock_test.go30 symbols
docs/rfcs/1/main_test.go28 symbols
types/iterator.generated.go26 symbols
pkg/iowrap/reader.go21 symbols
pairs/generated.go20 symbols

For agents

$ claude mcp add go-storage \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact

Ask about this repo answers extend the page