【go语言开发】Minio基本使用,包括环境搭建,接口封装和代码测试

2023-12-05

本文主要介绍go语言使用Minio对象存储,首先介绍搭建minio,创建bucket等,然后讲解封装minio客户端接口,包括但不限于:上传文件,下载,获取对象url,最后测试开发的接口

前言

Minio是一个开源的对象存储服务器 ,旨在提供高性能、可扩展和易于使用的存储解决方案。它兼容Amazon S3 API,因此可以与现有的S3工具和库集成,同时也提供了一套丰富的客户端SDK。

以下是Minio的一些主要特点:

  • 分布式架构 : Minio支持分布式部署,可以通过添加更多的节点来实现容量和性能的无缝扩展。它使用一致性哈希算法来分配对象到不同的节点上,从而实现负载均衡和数据冗余。

  • 高性能 : Minio采用了并发、异步和流式处理等技术,在保持数据完整性的同时,提供了出色的读写性能。它还支持多线程分段上传和下载,以加快大文件的传输速度。

  • 数据安全: Minio提供了多种数据保护机制,包括数据加密、访问控制列表(ACL)、策略和签名等。它还支持SSL/TLS加密传输,确保数据在传输过程中的安全性。

  • 易于使用 : Minio提供了简单而直观的API,可以轻松地进行对象存储操作,如创建存储桶、上传和下载文件、删除对象等。它还提供了Web管理界面,方便用户进行管理和监控。

  • 多语言支持 : Minio提供了多种编程语言的客户端SDK,包括Go、Java、Python、JavaScript等,使开发人员可以在不同的平台上使用自己熟悉的语言与Minio进行交互。

  • 可扩展性 : Minio可以轻松地与其他存储系统集成,如分布式文件系统、块存储和对象存储等。它还支持动态缩放和容器化部署,以适应不同规模和需求的应用场景。

Minio

docker安装minio

docker介绍和常用命令使用请参考: docker常用命令介绍

具体搭建步骤可以参考: docker安装minio

docker run -p 9000:9000 -p 9090:9090 \
 --name minio \
 -d --restart=always \
 -e "MINIO_ACCESS_KEY=admin" \
 -e "MINIO_SECRET_KEY=123456" \
 -v /root/docker/minio/data:/data  \
 -v /root/docker/minio/config:/root/.minio \
 minio/minio  server\
 /data --console-address ":9090" -address ":9000"

启动成功:

在这里插入图片描述

创建bucket,指定accesskey等

网页访问:http://localhost:9090/,端口号9090修改为你指定的端口号,一般常用9090或者9000。

红圈地方用于创建AccessKey和SecretKey,注意记得备份一下额~
在这里插入图片描述
创建Buckets:
在这里插入图片描述

客户端接口封装

这里封装了上传、下载、删除、列出指定buckets下的对象等常规接口,可以按照自己的需求更改~

package utils

import (
	"fmt"
	"github.com/minio/minio-go"
	"log"
	"os"
)

var MinioClientGlobal *MinioClient

type MinioClient struct {
	Client *minio.Client
}

// NewMinioClient 初始化minio
func NewMinioClient(endpoint, accessKey, secretKey string) (*MinioClient, error) {
	// 初始化 Minio 客户端
	minioClient, err := minio.New(endpoint, accessKey, secretKey, false)
	if err != nil {
		log.Println("new minio client fail: ", err)
		return nil, err
	}
	client := &MinioClient{
		Client: minioClient,
	}
	MinioClientGlobal = client
	return client, nil
}

// UploadFile 上传文件
func (m *MinioClient) UploadFile(bucketName, objectName, filePath string) error {
	// 打开本地文件
	file, err := os.Open(filePath)
	if err != nil {
		log.Printf("open filePath: %s fail: %s", filePath, err)
		return err
	}
	defer file.Close()

	// 上传文件到存储桶
	_, err = m.Client.PutObject(bucketName, objectName, file, -1, minio.PutObjectOptions{})
	if err != nil {
		log.Println("putObject fail: ", err)
		return err
	}

	fmt.Println("Successfully uploaded", objectName)

	return nil
}

// DownloadFile 下载文件
func (m *MinioClient) DownloadFile(bucketName, objectName, filePath string) error {
	// 创建本地文件
	file, err := os.Create(filePath)
	if err != nil {
		return err
	}
	defer file.Close()

	// 下载存储桶中的文件到本地
	err = m.Client.FGetObject(bucketName, objectName, filePath, minio.GetObjectOptions{})
	if err != nil {
		return err
	}

	fmt.Println("Successfully downloaded", objectName)
	return nil
}

// DeleteFile 删除文件
func (m *MinioClient) DeleteFile(bucketName, objectName string) (bool, error) {
	// 删除存储桶中的文件
	err := m.Client.RemoveObject(bucketName, objectName)
	if err != nil {
		log.Println("remove object fail: ", err)
		return false, err
	}

	fmt.Println("Successfully deleted", objectName)
	return true, err
}

// ListObjects 列出文件
func (m *MinioClient) ListObjects(bucketName, prefix string) ([]string, error) {
	var objectNames []string

	for object := range m.Client.ListObjects(bucketName, prefix, true, nil) {
		if object.Err != nil {
			return nil, object.Err
		}

		objectNames = append(objectNames, object.Key)
	}

	return objectNames, nil
}

// GetPresignedGetObject 返回对象的url地址,有效期时间为expires
func (m *MinioClient) GetPresignedGetObject(bucketName string, objectName string, expires time.Duration) (string, error) {
	object, err := m.Client.PresignedGetObject(bucketName, objectName, expires, nil)
	if err != nil {
		log.Println("get object fail: ", err)
		return "", err
	}

	return object.String(), nil
}

代码测试

如何编写测试代码,可以参考 【go语言开发】编写单元测试

下面是minio的配置,替换成自己的就可以

[minio]
MinioEndPoint = 127.0.0.1:9000
MinioAccessKey = NLtS0iNRFSCv6umJ
MinioSecretKey = 0cFaw1C0rp2CvhNIKYvAlqKrHNMB1rkn
MinioBucketName = go-blog
package test

import (
	"gin-blog/utils"
	"log"
	"testing"
)

const (
	filePath         = "./assets/test.txt"
	objectName       = "test.txt"
	downloadFilePath = "./assets/test2.txt"
)

// MinioInitTest 初始化minio client
func MinioInitTest() *utils.MinioClient {
	// 加载minio的endpoint等
	utils.InitConfig()
	log.Println(utils.MinioEndPoint, utils.MinioAccessKey, utils.MinioSecretKey)

	client, err := utils.NewMinioClient(utils.MinioEndPoint, utils.MinioAccessKey, utils.MinioSecretKey)
	if err != nil {
		log.Println("init minio fail")
		return nil
	}
	return client
}

// 测试上传文件
func TestMinioUpload(t *testing.T) {
	client := MinioInitTest()
	err := client.UploadFile(utils.MinioBucketName, objectName, filePath)
	if err != nil {
		t.Error("upload file: ", err)
	}
}

// 测试下载文件
func TestMinioDownloadFile(t *testing.T) {
	client := MinioInitTest()
	err := client.DownloadFile(utils.MinioBucketName, objectName, downloadFilePath)
	if err != nil {
		t.Error("download file: ", err)
	}
}

// 测试列出bucket下所有的对象
func TestListObjects(t *testing.T) {
	client := MinioInitTest()
	objects, err := client.ListObjects(utils.MinioBucketName, "")
	if err != nil {
		t.Error("list object: ", err)
	}
	log.Println("objects: ", objects)
}

// 删除对象
func TestDeleteFile(t *testing.T) {
	client := MinioInitTest()
	ret, err := client.DeleteFile(utils.MinioBucketName, objectName)
	if err != nil {
		t.Error("delete object: ", ret, err)
	}
	log.Println("delete object: ", ret)
}

// 获取对象,返回url,
func TestGetPresignedGetObject(t *testing.T) {
	client := MinioInitTest()
	object, err := client.GetPresignedGetObject(utils.MinioBucketName, objectName, 24*time.Hour)
	if err != nil {
		t.Error("GetPresignedGetObject: ", err)
	}
	log.Println("GetPresignedGetObject: ", object)
}

所有的接口都已经测试

上传文件:
在这里插入图片描述
在这里插入图片描述

获取对象url:
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【go语言开发】Minio基本使用,包括环境搭建,接口封装和代码测试 的相关文章

  • 使用 Go 解组嵌套 xml

    我有以下代码片段 我一直在努力让它工作 我到处寻找解决方案 但我找到的解决方案似乎都不起作用 我的映射似乎有问题xml Unmarshal命令 因为它涉及嵌套字段 下面的代码用于检索第一个被称为的值unit 并且位于 xml 代码的顶层 另
  • 从私钥中提取公钥

    我尝试通过以下方式以编程方式完成步骤 2 1 openssl genrsa out signing pem 2048 2 openssl rsa in signing pem outform PEM pubout out signing p
  • 切片文字中的求值顺序

    我最近浏览了Go的 语言规范 https golang org ref spec Order of evaluation https golang org ref spec Order of evaluation但发现评估顺序与本文档中解释
  • golang 范围内的指针不起作用

    为什么结果是A 1 A 2 A 2 not A 1 A 2 A 3 我们不能在范围内使用指针吗 这是代码 我设置了一个指针 指向范围循环 但它失败了 package main import fmt type A struct Barry B
  • 为什么空切片有 24 个字节?

    我想了解创建空切片时会发生什么make int 0 我执行此代码进行测试 emptySlice make int 0 fmt Println len emptySlice fmt Println cap emptySlice fmt Pri
  • 识别推文消息中正确的主题标签索引

    我需要识别 Twitter 消息 各种语言 表情符号等 中的正确索引 我找不到返回这些位置的解决方案 如下例所示 import regexp testing github com stretchr testify require func
  • 如何获取字段类型的零值

    我有一个包含许多字段的结构 我已经弄清楚如何使用反射提取字段名称 值和标签信息 我还想做的是确定字段的值是否与字段的默认值不同 目前 我有这个 有效 但有点臭 qsMap make map string interface var defa
  • 如何更新任意go结构的所有字符串字段?

    我尝试编写一个函数来更新所有字符串字段随意的结构体 像这样 type Student struct Name string Age int func SetStringField obj interface reflect ValueOf
  • 从头开始使用映像部署无法启动

    我正在使用以下内容构建图像Dockerfile FROM golang 1 19 2 bullseye as builder COPY src src WORKDIR src RUN CGO ENABLED 1 go build race
  • go:找到模块但不包含包

    我正在尝试安装 go 的网络包 但收到 不包含包错误 终端截图 我咨询过 go 模块 latest 已找到但不包含包 https stackoverflow com questions 62974985 go module latest f
  • 地图中的最大元素数

    GO 中的 Map 最多可以存储多少个元素 如果我需要经常从 Map 访问数据 那么在长时间运行的程序中不断向 Map 添加项目并从中检索项目是一个好主意吗 除了map length类型的最大值之外 map中的元素数量没有理论上的限制 in
  • 将具有联合字段的 C 结构映射到 Go 结构

    我从 Go 中的某些 WinApi 的系统调用中获取结果 我可以轻松地从 C 代码映射简单的结构 但是如何处理如下所示的 C 结构 typedef struct SPC LINK DWORD dwLinkChoice define SPC
  • golang:使用 gin 路由器服务 net.Conn

    我有一个处理传入 TCP 连接的函数 func Handle conn net Conn error 另外 我有一个初始化的 gin 路由器 带有已实现的句柄 router gin New router GET router POST Th
  • 将绝对路径和相对路径组合起来得到新的绝对路径

    我正在编写一个程序 其中一个组件必须能够采用给定的路径 例如 help index html or help 和基于该位置的相对路径 例如 otherpage index html or sub dir of help or help2 h
  • Go 中的切片分块

    我有一个切片 其中包含约 210 万条日志字符串 我想创建一个切片切片 其中字符串尽可能均匀分布 这是我到目前为止所拥有的 logs is a slice with 2 1 million strings in it var divided
  • golang从sdin扫描一行数字

    我正在尝试从标准输入读取输入 3 2 1
  • 如何使用 mongo-go-driver 有效地将 bson 转换为 json?

    我想将 bson 转换为mongo go 驱动程序 https github com mongodb mongo go driver有效地转换为 json 我应该小心处理NaN 因为json Marshal失败如果NaN存在于数据中 例如
  • 在 Go 中执行字节数组

    我正在尝试在 Go 程序中执行 shellcode 类似于使用其他语言执行此操作的方式 示例 1 C 程序中的 Shellcode https stackoverflow com questions 16626857 shellcode i
  • 使用 google.protobuf.Timestamp 在 Go 中解析带有时区偏移的日期时间戳

    我正在创建一个将使用 GRPC 和 protobuf 的 Go 应用程序 我的 RPC 服务应获取包含类型的消息google protobuf Timestamp 解析它并最终将其保存在数据库中或对其执行更多操作 我对什么被认为是该类型的有
  • Google Cloud Kubernetes 上任务队列的替代方案

    我发现任务队列主要用于App Engine标准环境 我正在将现有服务从 App Engine 迁移到 Kubernetes 任务队列的一个好的替代方案是什么 推送队列是当前正在使用的队列 我在线阅读文档并浏览了此链接 何时使用 PubSub

随机推荐