dongpeiwei8589 2018-02-03 22:22
浏览 45
已采纳

如何创建将容纳我的数据库和Redis连接的服务类型层

I am trying to prototype this little golang app and hoping to get some advice on how to go about managing my database and redis connection objects.

I want to create a a 'service layer' that will have all the product related logic, so maybe a ProductService.

I want ProductService to have a reference to both redis and my database client.

What would this ProductService look like roughly, and if I need to create a single instance of this and use it throughout the app do I define it in a 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))
}

My GetProducts handler has your regular signature:

func GetProducts(w http.ResponseWriter, r *http.Request) 

How am I suppose to pass in the ProductsService into this handler? It looks like the request/response are somehow automatically passed to this handler by MUX, so unsure how it can get a reference to the ProductService?

  • 写回答

2条回答 默认 最新

  • donglu3087 2018-02-03 22:29
    关注

    Create the product service with the fields you need:

    type ProductService struct {
       db *gorm.DB
       redis *redis.Client
    }
    

    Make GetProducts a method of ProductService:

    func (s *ProductService) GetProducts(w http.ResponseWriter, r *http.Request)  {
      // s.db is the database, s.redis is the redis client
    }
    

    Initialize ProductService in main. Use method values as handler functions:

    s := &ProductService{db: db, redis: redis}
    
    router.HandleFunc("/products", s.GetProducts).Methods("GET")
    

    An alternative to the method value is to use a closure to adapt a function to a handler function:

    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)
        }
    }
    

    Use

    router.HandleFunc("/products", s.Handler(PostPoduct)).Methods("POST")
    

    to register a function like this:

    func PostProduct(s *ProductService, w http.ResponseWriter, r *http.Request)  {
    }
    

    With this second approach, the ProductService layer can be kept separate from the individual handlers.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?