抽象掉 GO 中的持久层 [英] Abstracting away the persistence layer in GO

查看:19
本文介绍了抽象掉 GO 中的持久层的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以,我对 Go 编程的世界比较陌生,想知道在尝试抽象持久层时社区认为什么是最佳实践".

So, I'm relatively new to the world of Go programming and was wondering what the community considers to be "best practice" when attempting to abstract away the persistence layer.

在 DDD 中,这通常是通过引入存储库来处理的,该存储库向应用层公开了一组聚合.

In DDD this is often handled through the introduction of Repositories which exposes a set of Agreggates to an Application layer.

我担心的是,我过于习惯"从面向对象设计的角度思考这些问题,并想探索其他编程范式.

My concern is that I've been overly "conditioned" into thinking about these problems from the perspective of Object Oriented design and would like to explore other programming paradigms.

这也是我第一次尝试开发微服务;这也是我希望设计尽可能简单的部分原因.

This will also be my first attempt at developing micro-services; which is part of the reason why I'd like to keep my design as simple as possible.

推荐答案

我认为这个问题没有一个好的答案,多种方法可能是好的,一种从特定的角度更好,另一种更好另一个观点.

I don't think there's one good answer to this question, multiple approaches may be good, one better from a specific point of view, and another being better from another point of view.

只要尝试创建一个隐藏数据库特定行为和类型的接口(不是 Go 接口类型的含义),这将使您可以选择稍后轻松切换到新的数据库实现,因为所有其他部分您的代码通过此 DB 接口严格访问持久层.

Just try to create an interface (not in the meaning of Go interface type) that hides DB specific behavior and types, which will leave you the option to easily switch to a new db implementation later on, given that all other parts of your code strictly access the persistent layer via this DB interface.

DB 接口应该定义 Go 模型类型(存储在持久层中的建模数据),以及对这些类型的操作,例如加载、查找、保存.

The DB interface should define Go model types (modeling data stored in the persistent layer), and operations on these types, e.g. load, find, save.

以用户建模为例:

package db

type ID int64

type User struct {
    ID   ID
    Name string
}

// Manager contains the operations that involve the persistence layer.
type Manager interface {
    LoadUser(id ID) (*User, error)
    SaveUser(u *User) error
    FindUsersByName(name string) ([]*User, error)
    Close() error
}

您可以创建一个(或多个)Manager 接口的实现.使用 MongoDB 的实现:

And you may create an implementation (or multiple ones) of the Manager interface. An implementation using MongoDB:

package mongo

import (
    "db"
    "gopkg.in/mgo.v2"
)

// manager is a db.Manager implementation that uses MongoDB
type manager struct {
    // unexported fields, e.g. MongoDB session:
    sess *mgo.Sess
}

func (m *manager) LoadUser(id db.ID) (*db.User, error) { ... }

func (m *manager) SaveUser(u *db.User) error { ... }

func (m *manager) FindUsersByName(name string) ([]*db.User, error) { ... }

func (m *manager) Close() error {
    m.sess.Close()
    return nil
}

func New(mongoURL string) (db.Manager, error) {
    // Create, initialize your manager, and return it:
    sess, err := mgo.Dial(url)
    if err != nil {
        return nil, err
    }
    return &manager{sess: sess}, nil
}

db.Manager 实例(因为它涉及建立到(Mongo)DB 服务器的连接)应该尽可能长时间地保留(例如全局实例).根据使用情况,应该支持 Manager.Copy()Manager.Clone() 操作以获取副本或克隆以供短期使用(例如,为 HTTP 请求提供服务)).

A db.Manager instance (since it involves building a connection to a (Mongo)DB server) should be kept for as long as possible (e.g. global instance). Depending on the usage, Manager.Copy() and Manager.Clone() operations should be supported to acquire a copy or clone for short lived usage (e.g. serving an HTTP request).

使用这个例子:某个地方的某个人必须调用 mongo.New() 来获取 db.Manager 的值,但从那里我们只需要与持久层通过 Manager,将任何特定于数据库的细节留给实现.

Using this example: Someone somewhere has to call mongo.New() to acquire a value of the db.Manager, but from there we only have to interact with the persistence layer via the Manager, leaving any db specific detail to the implementation.

例如:

var mgr db.Manager
var err error

mgr, err = mongo.New("<mongodburl>")
if err != nil {
    log.Printf("Could not connect to db:", err)
    return
}
defer mgr.Close()

id := 123456
u, err := mgr.LoadUser(id)
if err != nil {
    log.Printf("Failed to load user [id: %v]: %v\n", id, err)
    return
}
fmt.Printf("Loaded User: %+v\n", u)

这篇关于抽象掉 GO 中的持久层的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆