1 回答
TA贡献1852条经验 获得超1个赞
这很大程度上是通过使用接口来实现的。
假设您创建一个 Web 应用程序并且想要显示用户。
首先,您需要定义一个接口,例如
type Creator interface{
Create(u User)(User,error)
}
type Reader interface{
Read(k PrimaryKey)(User, error)
ListAll()([]User,error)
ListPaginated(page, offset int)([]User,error)
}
type Updater interface{
Update(u User)(User, error)
UpdateByKey(k PrimaryKey, u User)(User, error)
UpdateMany(...User)error
}
type Deleter interface{
Delete(u User)error
DeleteMany(u ...User)error
DeleteByKey(keys ...PrimaryKey)error
}
type CRUD interface {
Creator
Reader
Updater
Deleter
}
接下来,为您想要支持的每种数据库类型实现 CRUD 接口。
现在,您可以创建一个处理程序:
// ListHandler uses an interface instead of a concrete type to
// retrieve the data from the databases.
// Not only does this approach make it possible to provide different
// implementations, but it makes unit testing way easier.
//
// "Thou Shalt Write Tests"
func ListHandler(rdr Reader) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Pagination ommited for brevity
// Note that the handler is agnostic of the underlying implementation.
u, err := rdr.ListAll()
if err != nil {
log.Printf("ListHandler: error retrieving user list: %s", err)
// Do not do this in production! It might give an attacker information
// Use a static error message instead!
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
if err := json.NewEncoder(w).Encode(u); err != nil {
log.Printf("ListHandler: error encoding user list to JSON: %s", err)
// See above
http.Error(w, err.Error(), http.StatusInternalServerError)
}
})
}
并设置如下:
func main() {
// Get your config
// Then simply use an implementation of CRUD
var dbConn CRUD
switch cfg.DbType {
case "myql":
// returns your implementation of CRUD using MySQL
dbConn = createMySQLConnector(cfg)
case "oracle":
// returns your implementation of CRUD using Oracle
dbConn = createOracleConnector(cfg)
}
http.Handle("/users/", ListHandler(dbConn))
log.Fatal(http.ListenAndServe("0.0.0.0:8080", nil))
}
哈
- 1 回答
- 0 关注
- 112 浏览
添加回答
举报