我正在尝试制作这个小型 golang 应用程序的原型(prototype),并希望就如何管理我的数据库和 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 的引用?
请您参考如下方法:
使用您需要的字段创建产品服务:
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 层可以与各个处理程序分开。