Go基礎學習記錄 – 編寫Web應用程 – 完善Blog Model

DurbanZhang發表於2019-02-16

完善Blog Model

前面的章節 我們分別介紹了MySQL、SQLite、PostgreSQL等資料庫的使用
本節簡單介紹並完善下我們自己的小部落格的Model部分,這部分暫時先分享下Blog Model部分
這部分的完善其實很簡單,但是對於像我這樣的初學者,還是稍微費力一點

為了保持專案的可學習性,我這裡將之前分享的程式碼積累了下,放在github上,想要儘快入手學習的,可以直接clone我的程式碼,寫程式碼不上手,都等於白搭,光看的話,對於我來說,我是不行的,沒辦法學會。

專案地址

https://github.com/durban89/wiki_blog
tag: 1.0.11

有些同學可能看不懂,怎麼就只給了這些,完全不懂呀。我把使用的命令打出來,照著操作,就應該可以解決了

git clone https://github.com/durban89/wiki_blog /local/path
cd /local/path
git fetch origin
git checkout 1.0.11

這些我覺得 夠清晰了。OK!

繼續分享”完善Model”。

在完善Model層之前我們先想一下,再進行部落格的資料互動上我們需要哪些基本功能,我列出如下

  • 增加 – 部落格空的,是不是我們需要增加的資料
  • 更新 – 如果釋出錯了,是不是需要進行更新
  • 刪除 – 如果發表的文章違法了,是不是需要進行刪除
  • 查詢 – 如果進行檢視,是不是需要把資料對出來,但是這裡有讀多條和一條的時候

好了功能我們大概知道了,下面我們先寫個增加的邏輯,修改blog.go,新增Create()函式

// Create 新增資料
func Create(p *helpers.Page) (int64, error) {
    sql := fmt.Sprintf("INSERT %s SET title=?", tableName)
    stmt, err := Conn.Prepare(sql)
    if err != nil {
        return 0, err
    }

    res, err := stmt.Exec(p.Title)
    if err != nil {
        return 0, err
    }

    id, err := res.LastInsertId()
    if err != nil {
        return 0, err
    }

    return id, nil
}

首先說下引數這裡引數的型別是Page,為什麼要用Page,其實很好理解,我們前面已經大致列出了一篇文章的主要結構,其實一篇文章的結構的基本上就是我們需要儲存的,Page的結構我這裡只是簡單加了一個ID,
其他項沒有修改,後面再繼續完善,一下子完善了,是需要花費蠻多時間的。Page目前的結構如下

type Page struct {
    ID     int         // 新加
    Title  string
    Body   []byte
    Script string
    Html   template.HTML
    Token  string
}

Create()函式暫時也儲存了標題內容,其餘的後期分享
返回的引數,這裡(int64, error),也很好理解,就是返回我們建立記錄的ID,其餘的更新和刪除功能都很類似下面列出如下

// Update 更新資料
func Update(p *helpers.Page, id int64) (int64, error) {
    sql := fmt.Sprintf("UPDATE %s SET title=? WHERE autokid=?", tableName)
    stmt, err := Conn.Prepare(sql)
    if err != nil {
        return 0, err
    }

    res, err := stmt.Exec(p.Title, id)
    if err != nil {
        return 0, err
    }

    affect, err := res.RowsAffected()
    if err != nil {
        return 0, err
    }

    return affect, nil
}
// Delete 刪除資料
func Delete(id int64) (int64, error) {
    sql := fmt.Sprintf("DELETE FROM %s WHERE autokid=?", tableName)
    stmt, err := Conn.Prepare(sql)
    if err != nil {
        return 0, err
    }

    res, err := stmt.Exec(id)
    if err != nil {
        return 0, err
    }

    affect, err := res.RowsAffected()
    if err != nil {
        return 0, err
    }

    return affect, nil
}
// Query 獲取資料
func Query() ([]helpers.Page, error) {
    sql := fmt.Sprintf("SELECT * FROM %s", tableName)
    rows, err := Conn.Query(sql)

    if err != nil {
        return nil, err
    }

    var res = []helpers.Page{}

    for rows.Next() {
        var autokid int
        var title string
        err = rows.Scan(&autokid, &title)

        if err != nil {
            return nil, err
        }

        p := helpers.Page{
            ID:    autokid,
            Title: title,
        }

        res = append(res, p)
    }

    return res, nil
}
// QueryOne 獲取一條資料
func QueryOne() ([]helpers.Page, error) {
    sql := fmt.Sprintf("SELECT * FROM %s LIMIT 0, 1", tableName)

    rows, err := Conn.Query(sql)

    if err != nil {
        return nil, err
    }

    var res = []helpers.Page{}

    for rows.Next() {
        var autokid int
        var title string
        err = rows.Scan(&autokid, &title)

        if err != nil {
            return nil, err
        }

        p := helpers.Page{
            ID:    autokid,
            Title: title,
        }

        res = append(res, p)
    }

    return res, nil
}

上面基本上就完成了Blog Model的基礎資料互動搭建,下面開始寫我們的測試單元,簡單的寫幾個測試,看看功能是否能夠執行,完整的測試後面來完善,測試單元程式碼如下

package models

import (
    "testing"

    "github.com/durban89/wiki/helpers"
)

func TestCreate(t *testing.T) {
    p := helpers.Page{
        Title: "Test Create",
    }
    id, err := Create(&p)
    if err != nil {
        t.Error(err)
    }

    t.Log(id)
}

func TestUpdate(t *testing.T) {
    p := helpers.Page{
        Title: "Test Update",
    }

    effect, err := Update(&p, 2)
    if err != nil {
        t.Error(err)
    }

    t.Log(effect)
}

func TestDelete(t *testing.T) {
    effect, err := Delete(2)
    if err != nil {
        t.Error(err)
    }

    t.Log(effect)
}

func TestQueryOne(t *testing.T) {
    row, err := QueryOne()

    if err != nil {
        t.Error(err)
    } else {
        t.Log(row)
    }

    if len(row) == 1 {
        t.Log("正確")
    } else {
        t.Error("失敗")
    }

    for i, k := range row {
        t.Log(i)
        t.Log(k)
    }
}

// TestQuery 測試獲取資料
func TestQuery(t *testing.T) {
    row, err := Query()

    if err != nil {
        t.Error(err)
    } else {
        t.Log(row)
    }

    if len(row) > 0 {
        t.Log("正確")
    } else {
        t.Error("失敗")
    }

    for i, k := range row {
        t.Log(i)
        t.Log(k)
    }
}

編譯並進行測試,測試通過類似如下

$ go test -v
=== RUN   TestCreate
--- PASS: TestCreate (0.01s)
        blog_test.go:18: 6
=== RUN   TestUpdate
--- PASS: TestUpdate (0.00s)
        blog_test.go:31: 1
=== RUN   TestDelete
--- PASS: TestDelete (0.00s)
        blog_test.go:40: 1
=== RUN   TestQueryOne
--- PASS: TestQueryOne (0.00s)
        blog_test.go:49: [{3 title2 []   }]
        blog_test.go:53: 正確
        blog_test.go:59: 0
        blog_test.go:60: {3 title2 []   }
=== RUN   TestQuery
--- PASS: TestQuery (0.00s)
        blog_test.go:71: [{3 title2 []   } {4 Test Create []   } {5 Test Create []   } {6 Test Create []   }]
        blog_test.go:75: 正確
        blog_test.go:81: 0
        blog_test.go:82: {3 title2 []   }
        blog_test.go:81: 1
        blog_test.go:82: {4 Test Create []   }
        blog_test.go:81: 2
        blog_test.go:82: {5 Test Create []   }
        blog_test.go:81: 3
        blog_test.go:82: {6 Test Create []   }
PASS
ok      github.com/durban89/wiki/models 0.030s

今天就分享到這裡,如果你有其他疑問請在下方留言或者加群交流

專案更新地址

https://github.com/durban89/typescript_demo.git
tag: 1.0.12

相關文章