小怪兽爱吃肉
这很大程度上是通过使用接口来实现的。假设您创建一个 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))}哈