我正在尝试对这个小golang应用程序进行原型设计,并希望就如何管理我的数据库和redis连接对象提供一些建议。
我想创建一个“服务层”,它将包含所有与产品相关的逻辑,因此可能是ProductService。
我希望ProductService能够引用redis和我的数据库客户端。
这个ProductService粗略地看起来是什么样的,如果我需要创建一个这样的实例并在整个应用程序中使用它,我是否在var中定义它?
func main() {
db, err := gorm.Open("postgres", "host=localhost user=blankman dbname=blank_development sslmode=disable password=")
if err != nil {
log.Fatalf("Got error when connect database, the error is '%v'", err)
}
defer db.Close()
redis := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "",
DB: 0,
})
pong, err := redis.Ping().Result()
fmt.Println(pong, err)
router := mux.NewRouter()
router.HandleFunc("/products", GetProducts).Methods("GET")
log.Fatal(http.ListenAndServe(":3001", router))
}
我的GetProducts处理程序有你的常规签名:
func GetProducts(w http.ResponseWriter, r *http.Request)
我想如何将ProductsService传入此处理程序?看起来请求/响应以某种方式由MUX自动传递给此处理程序,因此不确定如何获取对ProductService的引用?
答案 0 :(得分:1)
使用您需要的字段创建产品服务:
type ProductService struct {
db *gorm.DB
redis *redis.Client
}
使GetProducts成为ProductService的方法:
func (s *ProductService) GetProducts(w http.ResponseWriter, r *http.Request) {
// s.db is the database, s.redis is the redis client
}
在main中初始化ProductService。使用method values作为处理函数:
s := &ProductService{db: db, redis: redis}
router.HandleFunc("/products", s.GetProducts).Methods("GET")
方法值的替代方法是使用闭包来使函数适应处理函数:
func (s *ProductService) Handler(fn func(*ProductService, http.ResponseWriter, *http.Request)) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
fn(s, w, r)
}
}
使用
router.HandleFunc("/products", s.Handler(PostPoduct)).Methods("POST")
注册这样的函数:
func PostProduct(s *ProductService, w http.ResponseWriter, r *http.Request) {
}
使用第二种方法,ProductService层可以与各个处理程序分开。
答案 1 :(得分:1)
另一种选择是避免使用服务的结构并使用闭包(使用一个关闭依赖项的函数)来构建处理程序,如下所示:
func MakeGetProductsHander(db *gorm.DB, client *redis.Client) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// Use db and client in here...
}
}
然后像这样应用处理程序:
router.HandleFunc("/products", MakeGetProductsHander(db, client)).Methods("GET")
这会以更明确,更明显的方式将您的依赖项注入您的处理程序。
附注:将Redis客户端变量重命名为client
或其他内容,因为您通过调用它来redis
隐藏包名称。