Go Storage存储包封装
目的
封装存储包的目的是为了更方便地在项目中对数据在不同的媒介进行存储,可能是云存储,也可以是本地存储。并且提供对对象名检测,对权限的判断,就是为了减少使用者在存储时忽略的一些问题,从而避免可能产生的错误。另外,通过配置文件的参数切换,可以在不修改代码的前提下,切换存储媒介。
若有自己的存储媒介,实现stroage.go里面的interface,并且调用storage.Register即可。
存储媒介
目前,提供了对本地存储(fs),青云存储(qs),腾讯云(cos)存储的封装。
github地址
Interface
type Storage interface {
//把一个文件当做对象,读写即为,Get和Put
Init(cfg string) (Storage, error)
// 保存data至某个文件
Put(key string, r io.Reader, contentLength int64) error
// 根据某个文件写入到另一个文件里
PutByPath(key string, /*要带上路径,相对路径或绝对路径都行*/src string) error
// 获取语音流
FileStream(key string) (io.ReadCloser, *FileInfo, error)
// 获取数据
Get(key string, wa io.WriterAt) error
// 获取到某个文件
GetToPath(key string, /*要带上路径,相对路径或绝对路径都行*/dest string) error
// 获取文件信息 大小,修改时间,权限
Stat(key string) (*FileInfo, error)
// 删除文件
Del(key string) error
// 获取文件大小
Size(key string) (int64, error)
// 判断文件是否存在
IsExist(key string) (bool, error)
}
提供的方法
以本地存储为例(FS),所有的范例代码都在上面的github上
初始化
storageType = fs
storageConf = {"BaseDir":"./testData"}
fsStorage, err := storage.Init(cfg.storageType,cfg.storageConf)
if err != nil {
fmt.Printf("err : %s\n", err.Error())
return
}
本地存储初始化,直接call storage.Init()即可。如果是非封装好的storage type,则会返回错误,无该类型,或者没有Register到storage里面。
base dir参数主要是为了文件夹的prefix,因为在多数情况下(根据自己写的项目),保存的路径前缀都是一样的,只是在一个根目录下有不同的文件夹分类存储。所以通过base dir定义,可以在后面的操作自动拼接上base dir,而不会漏掉。当然,没有写也是没有问题的。
保存data至某个对象
Put(key string, r io.Reader, contentLength int64) error
put方法从任何一个可读的object读取数据保存到对应的路径下面,该方法,会对存储的权限,对象名做校验,从而不用担心返回的错误是系统返回的而不知道为何。
buf := bytes.NewBuffer(nil)
buf.WriteString("this is test!")
if err := fsStorage.Put("test_fs.txt", buf, int64(buf.Len())); err != nil {
fmt.Printf("fs put err : %s\n", err.Error())
return
}
从某个对象中读取数据,并存储到另一个对象
PutByPath(key string, src string) error
这个方法是从一个对象读取数据,然后存到对应的路径下面。这个方法会检查src是否存在,如果不存在也直接返回错误。src的地址必须是相对路径或者是绝对路径,这个src不会拼上base dir。
err := fsStorage.PutByPath("test_fs_put_by_path.txt", "../testdata/test_fs.txt")
if err != nil {
return er
}
获取文件流
FileStream(key string) (io.ReadCloser, *FileInfo, error)
如果对象内容为空会返回对象内容为空的错误
fd,stat,err := fsStorage.FileStraem("test_fs_put_by_path.txt")
if err != nil {
return err
}
获取对象
Get(key string, wa io.WriterAt) error
Get方法从一个object获取数据并写入到一个writeAter。
fd, _ := os.OpenFile("test.txt", os.O_CREATE|os.O_RDWR|os.O_APPEND, 0766)
err := fsStorage.Get("test_fs_put_by_path.txt", fd)
if err != nil {
return err
}
defer fd.close()
获取对象到指定对象
GetToPath(key string, dest string) error
GetToPath方法从一个object写入到另一个对象,这个方法分别会对这两个路径做权限,对象名校验。dest的地址必须是相对路径或者是绝对路径,这个dest不会拼上base dir。
if err := fsStorage.GetToPath("test_fs_put_by_path.txt", "../test.txt") ; err != nil {
获取对象信息
Stat(key string) (*FileInfo, error)
if err := fsStorage.GetToPath("test_fs_put_by_path.txt", "../test.txt") ; err != nil {
return err
}
stat,err := fsStorage.Stat("test_get_to_path.txt");
if err != nil {
return err
}
fmt.Sprintf("%v\n",stat)
删除对象
Del(key string) error
Del方法如果删除的是一个没有权限的或者不存在的文件,也会返回相应的error
if err := fsStorage.Del("test_get_to_path.txt"); err != nil {
return err
}
获取对象大小
Size(key string) (int64, error)
会先判断对象是否存在,如果不存在会返回相应错误
size,err := fsStorage.Size("test_get_to_path.txt");
if err != nil {
return err
}
fmt.Println(size)
判断对象是否存在
IsExist(key string) (bool, error)
exist, err := fsStorage.IsExist("test.txt")
if err != nil {
return err
}
fmt.Sprintf("%v\n",exist)
RoadMap
把string格式的config改成,通过配置文件直接匹配的方式,更加方便;
提供主要存储和次要存储的绑定,在项目里可以使用多个存储;
Others
storage基于朋友ymc的基础上再次封装修改
欢迎指点和吐槽