Golang如何执行依赖注入来存储一些字符串值

时间:2016-07-04 02:57:07

标签: go

我正在使用mysql数据库,并且有许多与数据库交互的不同函数/方法。对于每个功能,我必须提供数据库凭证,例如

ReadAll.go

func ReadAll() {
    db, err := sql.Open("mysql",
        "user:password@tcp(127.0.0.1:3306)/hello")
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()
}

“mysql”的一部分,             “user:password @ tcp(127.0.0.1:3306)/ hello”永远不会更改,我将其提供给与DB交互的每个Function。我想知道如何创建一个新文件说 DataBase.go 将这些凭据放入某个全局变量然后在需要这些字符串时引用?这样,如果我必须更改凭据,我只需要在一个地方更改它们。 我想做像

这样的事情

Database.go

const GlobalDB := "mysql","user:password@tcp(127.0.0.1:3306)/hello"

然后

ReadAll.go

func ReadAll() {
    db, err := sql.Open(GlobalDB)
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()
}

我是Golang的新手,但试图解决这个问题。

3 个答案:

答案 0 :(得分:3)

我可能会通过打开一次数据库会话,然后将此会话传递给可能需要它的任何函数或方法。这有一些潜在的问题:

  • 您可能需要锁定对它的访问权限,因此您不必在同一会话中混合多个查询(但可能是您的数据库库确保了这一点,FWIW" database / sql&#34 ;是并发安全的,建议不要打开短期数据库连接)
  • 您无法安全地关闭会话,因为它可能仍在其他地方使用。

另一种方法是使用一个返回DB sesssion的函数,而不是执行:

$(document).ready(function(){
  $("#select_users").on('change', function(){
    var user = $(this).val();
    var path = $("#btn_book").attr("data-book-path");
    $("#btn_book").attr('href', path + "/" + user);
    //#btn_book is the id of our link, where we'll change its href to the selected user
  });
});

您执行以下操作:

db, err := sql.Open("mysql", "user:password@tcp(127.0.0.1:3306)/hello")

如果您想要更多灵活性,可以使用包含所需数据的结构,然后从中构建数据库连接参数。

func dbSession() (sql.DB, error) {
  return sql.Open("mysql", "credentials")
}

func ReadAll() {
    db, err := dbSession()
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close() 
}

另请注意type dbData struct { DBType, DBName, User, Host, Password string } var DBData dbData func dbSession() (*sql.DB, error) { return sql.Open(DBData.DBType, fmt.Sprintf("%s:%s@tcp(%s)/%s", DBData.User, DBData.Password, DBData.Host, DBData.DBName) } 的文档中的以下内容:

  

返回的数据库对于多个goroutine和并发使用是安全的   维护自己的空闲连接池。因此,Open功能   应该只召唤一次。很少需要关闭数据库。

答案 1 :(得分:1)

您可以使用凭据轻松创建新文件。只需将文件放在主包主文件中即可。

package main

var myDBConnectionString := "mysql://...."

编译源代码时将包含此内容。

问题是,每次必须连接到另一个数据库时都必须重新编译代码。想想开发系统与生产系统。这些系统中的数据库凭据应该不同,对吧? :)

要解决这个问题,有一个配置文件是很常见的。因此,您无需重新编译代码即可更改凭据。

我还有另一个想法 - 只需连接到db一次,然后全局访问此资源。     包主要

import (
    "fmt"
)

var myDb = "example"

func main() {
    fmt.Println("Hello, playground")
    doSomthingWithDatabase()
}

func doSomthingWithDatabase() {
   fmt.Println("We can access a global variable here, see", myDb)
}

https://play.golang.org/p/npZ6Z49ink

对于配置处理,您可以在此处查看 https://blog.gopheracademy.com/advent-2014/reading-config-files-the-go-way/

答案 2 :(得分:1)

hiboot-data提供了符合您要求的开箱即用的启动器,该启动器为github.com/hidevopsio/hiboot-data/starter/gorm,或者您可以使用hiboot来实现自己的启动器框架,然后可以在任何地方注入以与创建数据库配置脱钩。

package service


import (
    "errors"
    "hidevops.io/hiboot-data/examples/gorm/entity"
    "hidevops.io/hiboot-data/starter/gorm"
    "hidevops.io/hiboot/pkg/app"
    "hidevops.io/hiboot/pkg/utils/idgen"
)

type UserService interface {
    AddUser(user *entity.User) (err error)
    GetUser(id uint64) (user *entity.User, err error)
    GetAll() (user *[]entity.User, err error)
    DeleteUser(id uint64) (err error)
}

type UserServiceImpl struct {
    // add UserService, it means that the instance of UserServiceImpl can be found by UserService
    UserService
    repository gorm.Repository
}

func init() {
    // register UserServiceImpl
    app.Component(newUserService)
}

// will inject BoltRepository that configured in github.com/hidevopsio/hiboot/pkg/starter/data/bolt
func newUserService(repository gorm.Repository) UserService {
    repository.AutoMigrate(&entity.User{})
    return &UserServiceImpl{
        repository: repository,
    }
}

func (s *UserServiceImpl) AddUser(user *entity.User) (err error) {
    if user == nil {
        return errors.New("user is not allowed nil")
    }
    if user.Id == 0 {
        user.Id, _ = idgen.Next()
    }
    err = s.repository.Create(user).Error()
    return
}

func (s *UserServiceImpl) GetUser(id uint64) (user *entity.User, err error) {
    user = &entity.User{}
    err = s.repository.Where("id = ?", id).First(user).Error()
    return
}

func (s *UserServiceImpl) GetAll() (users *[]entity.User, err error) {
    users = &[]entity.User{}
    err = s.repository.Find(users).Error()
    return
}

func (s *UserServiceImpl) DeleteUser(id uint64) (err error) {
    err = s.repository.Where("id = ?", id).Delete(entity.User{}).Error()
    return
}