跳转到主要内容

在本教程中,我们将了解如何使用 Go-ORM 或 GORM 以简单的方式与 sqlite3 数据库进行交互。

ORM 或对象关系管理器几乎充当我们开发人员和我们底层数据库技术之间的中介。 它们让我们基本上可以像往常一样使用对象,然后保存这些对象,而无需编写复杂的 SQL 语句。

在您不希望使用 SQL 但需要数据库的情况下,它们有效地降低了我们代码库的复杂性。

视频教程

https://youtu.be/VAGodyl84OY

安装


为了安装 jinzhu/gorm,您必须执行以下 go get 命令:

go get -u github.com/jinzhu/gorm


完成此操作后,您应该能够将 jinzhu/gorm 导入到任何基于 Go 的项目中。

一个简单的例子


例如,假设您想编写一个 go REST API,当某个 API 端点被命中时,它将新用户及其电子邮件保存到数据库中。

我们可以像这样在 go 结构中描述我们的用户:

// Our User Struct
type User struct {
    gorm.Model
    Name  string
    Email string
}


一旦我们定义了我们的用户模型,我们就可以开始公开一个 API 端点,可以将新用户保存到我们的 sqlite3 数据库。

注意 - 如果您想知道如何开发自己的基于 Go 的 REST API,请查看我的其他 Go 教程:在 Go 中构建 RESTful API

我们的 API


因此,我们将创建一个非常简单的 API,它具有 4 个不同的 CRUD 端点。这些将返回所有用户、添加新用户、删除用户和更新用户。

在我们新的 GORM 的帮助下,如果我们采用标准的原始 SQL 路径,这些端点的创建应该比它们本来的要简单得多。

package main

import (
    "fmt"
    "log"
    "net/http"

    "github.com/gorilla/mux"
)

func allUsers(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "All Users Endpoint Hit")
}

func newUser(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "New User Endpoint Hit")
}

func deleteUser(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Delete User Endpoint Hit")
}

func updateUser(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Update User Endpoint Hit")
}

func handleRequests() {
    myRouter := mux.NewRouter().StrictSlash(true)
    myRouter.HandleFunc("/users", allUsers).Methods("GET")
    myRouter.HandleFunc("/user/{name}", deleteUser).Methods("DELETE")
    myRouter.HandleFunc("/user/{name}/{email}", updateUser).Methods("PUT")
    myRouter.HandleFunc("/user/{name}/{email}", newUser).Methods("POST")
    log.Fatal(http.ListenAndServe(":8081", myRouter))
}


func main() {
    fmt.Println("Go ORM Tutorial")

    // Handle Subsequent requests
    handleRequests()
}

然后我们可以通过运行 go run main.go 来启动这个新的 API。 这个 API 代表了我们构建基于 ORM 的解决方案的基础。

SQLite3 数据库创建和自动模式迁移


我们项目的下一步是创建一个数据库。 出于本教程的目的,我们将使用 sqlite3 数据库,因为它易于使用和设置。

注意 - 您可以通过切换方言使用 GORM 相当轻松地切换到使用另一种数据库技术。

我们可以使用 GORM 通过调用 db.AutoMigrate(&User{}) 在我们的数据库中自动创建用户表。 这为我们省去了编写表创建 SQL 脚本的麻烦。

// our initial migration function
func initialMigration() {
    db, err := gorm.Open("sqlite3", "test.db")
    if err != nil {
        fmt.Println(err.Error())
        panic("failed to connect database")
    }
    defer db.Close()

    // Migrate the schema
    db.AutoMigrate(&User{})
}

func main() {
    fmt.Println("Go ORM Tutorial")

    // Add the call to our new initialMigration function
    initialMigration()

    handleRequests()
}

更新我们的所有用户端点


在我们的 allUsers() 函数中,我们基本上想查询数据库中的所有用户记录,然后将其编码为 JSON 并将其作为响应返回。

我们可以通过调用 db.Find(&users) 来查询数据库中的所有用户。

func allUsers(w http.ResponseWriter, r *http.Request) {
    db, err := gorm.Open("sqlite3", "test.db")
    if err != nil {
        panic("failed to connect database")
    }
    defer db.Close()

    var users []User
    db.Find(&users)
    fmt.Println("{}", users)

    json.NewEncoder(w).Encode(users)
}

更新我们的新用户端点


我们现在想要更新我们的 newUser() 函数,以便它可以将新用户插入到我们的数据库中。 这将需要从向我们的 API 发出的请求的查询参数中解析用户名和电子邮件。

这将不得不解析我们端点的路径参数,然后使用这些路径参数来填充一个新的用户对象,然后我们将通过调用 db.Create(&User{Name: name, Email: email}) 将其插入到我们的 sqlite 数据库中 所以:

func newUser(w http.ResponseWriter, r *http.Request) {
    fmt.Println("New User Endpoint Hit")

    db, err := gorm.Open("sqlite3", "test.db")
    if err != nil {
        panic("failed to connect database")
    }
    defer db.Close()

    vars := mux.Vars(r)
    name := vars["name"]
    email := vars["email"]

    db.Create(&User{Name: name, Email: email})
    fmt.Fprintf(w, "New User Successfully Created")
}

我们的删除用户端点


我们的 deleteUser() 函数将删除与通过路径参数传递给它的同名用户匹配的用户。 它相当基本,不能处理数据库中存在多个用户的情况,但它在这个项目中提供了一个很好的例子。

func deleteUser(w http.ResponseWriter, r *http.Request) {
    db, err := gorm.Open("sqlite3", "test.db")
    if err != nil {
        panic("failed to connect database")
    }
    defer db.Close()

    vars := mux.Vars(r)
    name := vars["name"]

    var user User
    db.Where("name = ?", name).Find(&user)
    db.Delete(&user)

    fmt.Fprintf(w, "Successfully Deleted User")
}

我们的更新用户端点


在您需要更新数据库中的现有用户的奇怪情况下,您当然可以使用 GORM 以更简单的方式完成此操作。 本质上,您要做的是使用唯一名称搜索给定用户。

一旦你有了这个用户,你只需像通常更新标准的 go 对象一样更新 User 对象。 一旦您对对象和更新感到满意,您就可以调用 db.Save(&user) 来保存对数据库的任何更改。

func updateUser(w http.ResponseWriter, r *http.Request) {
    db, err := gorm.Open("sqlite3", "test.db")
    if err != nil {
        panic("failed to connect database")
    }
    defer db.Close()

    vars := mux.Vars(r)
    name := vars["name"]
    email := vars["email"]

    var user User
    db.Where("name = ?", name).Find(&user)

    user.Email = email

    db.Save(&user)
    fmt.Fprintf(w, "Successfully Updated User")
}

完整的源代码


如果您想要该项目的完整源代码,请查看以下要点:https://gist.github.com/elliotforbes/e241eaa8cc9d7bf3ec75b333e891d422

结论


希望您发现本教程很有用,它向您展示了在使用数据库时使用 ORM 的优势。 如果这有帮助,或者您认为您需要进一步的帮助,请在下面的评论部分告诉我!

文章链接