Go中的数据层次抽象

huangapple go评论92阅读模式
英文:

Tier abstraction of data in Go

问题

我将为您翻译以下内容:

我打算在Go中创建一个项目,但我希望将我的层进行分离。我的目标是创建一个类似DAO模式的代码包,即我希望我的调用者只能与服务的接口进行通信(可能是另一个项目),而不是与具体实现进行通信。这样可以避免将来更改数据库时,调用者不需要更改,并且对此更改应该是透明的。

我考虑创建一个名为"db"的项目,其中包含一个名为"persistence"的文件和一个名为"persistence"的包。

package persistence

// 需要从服务(另一个项目)中使用的CRUD接口
type Recorder interface {
    SelectKey([]byte) error
    Insert([]byte, []byte) error
    Update([]byte, []byte) error
    Delete([]byte) error
}

// Oracle的结构体
type ManageDataOracle struct {
}

// 二叉树的结构体
type ManageDataBinaryTree struct {
}

// MongoDB的结构体
type ManageDataMongoDb struct {
}

// Oracle的实现
func (memory *ManageDataOracle) SelectKey(pKey []byte) error {
    // Oracle的逻辑在这里
    return nil
}

func (memory *ManageDataOracle) Insert(pKey []byte, pValue []byte) error {
    // Oracle的逻辑在这里
    return nil
}

func (memory *ManageDataOracle) Update(pKey []byte, pValue []byte) error {
    // Oracle的逻辑在这里
    return nil
}

func (memory *ManageDataOracle) Delete(pKey []byte) error {
    // Oracle的逻辑在这里
    return nil
}

// 二叉树的实现
func (memory *ManageDataBinaryTree) SelectKey(pKey []byte) error {
    // 二叉树的逻辑在这里
    return nil
}

func (memory *ManageDataBinaryTree) Insert(pKey []byte, pValue []byte) error {
    // 二叉树的逻辑在这里
    return nil
}

func (memory *ManageDataBinaryTree) Update(pKey []byte, pValue []byte) error {
    // 二叉树的逻辑在这里
    return nil
}

func (memory *ManageDataBinaryTree) Delete(pKey []byte) error {
    // 二叉树的逻辑在这里
    return nil
}

// MongoDB的实现
func (memory *ManageDataMongoDb) SelectKey(pKey []byte) error {
    // MongoDB的逻辑在这里
    return nil
}

func (memory *ManageDataMongoDb) Insert(pKey []byte, pValue []byte) error {
    // MongoDB的逻辑在这里
    return nil
}

func (memory *ManageDataMongoDb) Update(pKey []byte, pValue []byte) error {
    // MongoDB的逻辑在这里
    return nil
}

func (memory *ManageDataMongoDb) Delete(pKey []byte) error {
    // MongoDB的逻辑在这里
    return nil
}

对于如何进行概念分离或如何从另一个项目中调用上述代码,您有什么建议吗?

英文:

I am going to create a project in Go, but I want to separate my tiers. My goal is create a package that has code something like the DAO pattern, i.e. I wish that my caller should only communicate with the interface of the service (which might be another project) and not with the implementation. This is to avoid the situation of a future change to the database, the caller should not change and should be transparent to this change.

I was thinking of creating a project db that contains a file called persistence with a package persistence as well

http://play.golang.org/p/O9b93F4LJp

package persistence
// Interface that have the CRUD which I need to use from service(another project)
type Recorder interface {
Selectkey([]byte) (err error)
Insert([]byte, []byte) (err error)
Update([]byte, []byte) (err error)
Delete([]byte) (err error)
}
// Struct for Oracle
type ManageDataOracle struct {
}
// Struct for binaryTree
type ManageDataBInaryTree struct {
}
// Struct for MongoDB
type ManageDataMongoDb struct {
}
// Implemtations for Oracle
func (memory *ManageDataOracle) SelectKey(pKey []byte) error {
// Logic for Oracle Here
return nil
}
func (memory *ManageDataOracle) Insert(pKey []byte, pValue []byte) error {
// Logic for Oracle Here
return nil
}
func (memory *ManageDataOracle) Update(pKey []byte, pValue []byte) error {
// Logic for Oracle Here
return nil
}
func (memory *ManageDataOracle) Delete(pKey []byte) error {
// Logic for Oracle Here
return nil
}
// Implemtations for Binary Tree
func (memory *ManageDataBInaryTree) SelectKey(pKey []byte) error {
// Logic for Binary tree Here
return nil
}
func (memory *ManageDataBInaryTree) Insert(pKey []byte, pValue []byte) error {
// Logic for Binary tree Here
return nil
}
func (memory *ManageDataBInaryTree) Update(pKey []byte, pValue []byte) error {
// Logic for Binary tree Here
return nil
}    
func (memory *ManageDataBInaryTree) Delete(pKey []byte) error {
// Logic for Binary tree Here
return nil
}
// Implemtations for Mongo DB
func (memory *ManageDataMongoDb) SelectKey(pKey []byte) error {
// Logic for MongoDB Here
return nil
}
func (memory *ManageDataMongoDb) Insert(pKey []byte, pValue []byte) error {
// Logic for MongoDB Here
return nil
}
func (memory *ManageDataMongoDb) Update(pKey []byte, pValue []byte) error {
// Logic for MongoDB Here
return nil
}
func (memory *ManageDataMongoDb) Delete(pKey []byte) error {
// Logic for MongoDB Here
return nil
}

Any advice on how to do this separation of concepts, or how the previous code should be called from another project?

答案1

得分: 0

你正在走在正确的道路上,但是不同的持久化机制将使用不同的键类型(例如,在Oracle中使用整数,在Mongo中使用类似字符串的标识符)。

将数据序列化为[]byte应该由抽象层处理,因为不同的底层持久化引擎将使用不同的数据表示形式。例如,考虑一个整数及其字节顺序。

因此,我建议将接口的签名更改为以下形式:

type Recorder interface {
    SelectByKey(interface{}) error
    DeleteByKey(interface{}) error
    Insert(interface{}, interface{}) error
    Update(interface{}, interface{}) error
}

这样,如果给定的键不是特定实现所需的正确类型,你还可以在SelectByKey等方法中使用panic。如果事先对键进行序列化,这将是不可能的,并且会导致问题。

英文:

You are on the right track but different persistence mechanisms will use different key types (for example an integer in an oracle and a string-like identifier in mongo).

The serialization of your data into []byte should be handled by the abstraction layer because different underlying persistence engines will use different representations of your data. Consider for instance an integer and it's endianness.

Hence I would change the signatures of your interface to the following:

type Recorder interface {
SelectByKey(interface{}) error
DeleteByKey(interface{}) error
Insert(interface{}, interface{}) error
Update(interface{}, interface{}) error
}

this way you can also panic inside, say SelectKey if the given key is not of the correct type for a specific implementation. This wouldn't be possible if you serialized your key beforehand and would lead to trouble.

答案2

得分: 0

我认为你需要类似这样的东西:

https://github.com/qiangxue/golang-restful-starter-kit

这个起始套件旨在为你提供一个在Go中开发RESTful服务的最佳项目结构。该套件遵循SOLID原则,鼓励编写清晰和惯用的Go代码的最佳实践。

该套件提供了以下功能:

  • 符合广泛接受的标准CRUD格式的RESTful端点
  • 基于JWT的身份验证
  • 通过环境变量和配置文件进行应用程序配置
  • 带有上下文信息的结构化日志记录
  • Panic处理和正确的错误响应生成
  • 自动处理数据库事务
  • 数据验证
  • 完整的测试覆盖
英文:

I think you need something like this:

https://github.com/qiangxue/golang-restful-starter-kit

> This starter kit is designed to get you up and running with a project
> structure optimal for developing RESTful services in Go. The kit
> promotes the best practices that follow the SOLID principles and
> encourage writing clear and idiomatic Go code.
>
> The kit provides the following features right out of the box
>
> RESTful endpoints in the widely accepted format Standard CRUD
> operations of a database table JWT-based authentication Application
> configuration via environment variable and configuration file
> Structured logging with contextual information Panic handling and
> proper error response generation Automatic DB transaction handling
> Data validation Full test coverage

huangapple
  • 本文由 发表于 2014年4月11日 05:13:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/22999131.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定