猿问

这种依赖注入模式线程安全吗?

我很难想出一个干净的模式来在 REST 服务器中注入依赖项,从而允许我编写独立的单元测试。下面的结构似乎有效,但我不确定它是否是线程安全的。


店铺:


package store


type InterfaceStore interface {

    Connect()

    Disconnect()

    User() interfaceUser

}


// Wiring up

type store struct {

    db *mongo.Database

}


func (s *store) Connect() {

    client, err := mongo.Connect()

    if err != nil {

        log.Fatal(err.Error())

    }


    s.db = client.Database()

}


func (s *store) Disconnect() {

    s.db.Client().Disconnect(context.TODO())

}


func (s *store) User() interfaceUser {

    return &user{s.db}

}



// Exposed from the package to create a store instance

func GetStore() InterfaceStore {

    return &store{}

}



// User related

type interfaceUser interface {

    InsertOne(models.User) (string, error)

}


type user struct {

    db *mongo.Database

}


func (u *user) InsertOne(user models.User) (primitive.ObjectID, error) {

    collection := u.db.Collection(collectionUsers)

    // persisting user in DB

}

服务器:


package server


type server struct{}


func (s *server) Start() {

    storeInstance := store.GetStore()

    storeInstance.Connect()

    defer storeInstance.Disconnect()


    r := gin.Default()

    keys := keys.GetKeys()


    routes.InitRoutes(r, storeInstance)


    port := fmt.Sprintf(":%s", keys.PORT)


    r.Run(port)

}


func CreateInstance() *server {

    return &server{}

}

路线:


package routes


func InitRoutes(router *gin.Engine, store store.InterfaceStore) {

    router.Use(middlewares.Cors)


    // createSubrouter creates a Gin routerGroup with the prefix "/user"

    userRoutes(createSubrouter("/user", router), store)

}


func userRoutes(router *gin.RouterGroup, store store.InterfaceStore) {

    controller := controllers.GetUserController(store)


    router.GET("/", controller.Get)

}

控制器:


package controllers


type userControllers struct {

    UserService services.InterfaceUser

}



通过使用接口,我可以在为控制器编写测试时模拟整个服务,并且我可以模拟整个存储来测试服务组件而无需访问数据库。


我想知道商店实例是否在代码之间安全共享,因为接口不是指针。这是否意味着store每次我将它向下传递时都会创建一个副本?


森栏
浏览 130回答 1
1回答

繁星coding

type user struct {}定义状态store是实现store.InterfaceStore接口的任何东西。如果你仔细看,你正在用指针接收器来实现它。这意味着(由 the 指向的实例)接收器将被共享。如果你的模拟通过值类型实现它们,它将在方法调用时被复制,你会很安全,但这也意味着这个模拟在方法调用后不会保持新状态,我猜这不是你的想。归根结底,这不是关于你如何在结构中定义它,按值或按引用,而是方法接受什么作为接收者。
随时随地看视频慕课网APP

相关分类

Go
我要回答