Closed. This question needs details or clarity。它当前不接受答案。












想改善这个问题吗?添加详细信息,并通过editing this post阐明问题。

4年前关闭。



Improve this question




因此,我对Go编程世界比较陌生,想知道在尝试抽象化持久层时社区认为什么是“最佳实践”。

在DDD中,这通常通过引入存储库来解决,该存储库向应用程序层公开了一组Agreggate。

我担心的是,我已经过分“适应”了从面向对象设计的角度来考虑这些问题,并想探索其他编程范例。

这也是我开发微服务的第一次尝试;这就是为什么我想让我的设计尽可能简单的原因之一。

最佳答案

我认为这个问题没有一个好的答案,多种方法可能是好的,从特定的角度来看一种更好,而从另一角度来看则更好。

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

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

例如,为用户建模:

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接口(interface)的一个(或多个)实现。使用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请求)。

使用此示例:某处的人必须调用mongo.New()来获取db.Manager的值,但是从那里我们只需要通过Manager与持久层进行交互,就可以将任何特定于数据库的细节留给实现。

例如:
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 - 在GO中抽象掉持久层,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40333799/

10-11 09:17