這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
上一節已將將需要的資料從網站http://www.gratisography.com/ 抓取並存入資料庫【使用crawldata.go
中的InsertData(&imageDatas)
函數】,現在需要將資料從資料庫indiepic
的表gratisography
中取出並然會json
格式的資料。
專案檔夾結構如下:
indiepic├── README.md├── crawldata│ ├── crawldata.go│ └── database.go└── indiepic.go
現在將擷取資料的函數寫在database.go
中:
func GetAllImages() (imageDatas ImageDatas, err error) { // 串連資料庫 db, err := OpenDatabase() if err != nil { fmt.Printf(s.Join([]string{"串連資料庫失敗", err.Error()}, "-->")) return nil, err } defer db.Close() // Prepare statement for inserting data imgOut, err := db.Query("SELECT * FROM gratisography") if err != nil { fmt.Println(s.Join([]string{"擷取資料失敗", err.Error()}, "-->")) return nil, err } defer imgOut.Close() // 定義掃描select到的資料庫欄位的變數 var ( id int img_url string type_name string title string width int height int create_time string ) for imgOut.Next() { // db.Query()中select幾個欄位就需要Scan多少個欄位 err := imgOut.Scan(&id, &img_url, &type_name, &title, &width, &height, &create_time) if err != nil { fmt.Println(s.Join([]string{"查詢資料失敗", err.Error()}, "-->")) return nil, err } else { imageData := ImageData{img_url, type_name, title, width, height} imageDatas = append(imageDatas, imageData) } } return imageDatas, nil}
值得一提的是在SELECT
語句中拿到多少個欄位就需要在Scan
的時候使用變數去擷取多少個欄位,否測會報錯。所以建議不要像上面那樣SELECT *
,而是指定需要的欄位如SELECT id,img_url,title FROM tableName
。
GetAllImages()
函數返回兩個參數imageDatas ImageDatas
、err error
。
雖然使用GO自己寫一個HTTP請求很簡單,但為了更好地處理路由和資料,這裡使用一個web架構martini Classy web framework for Go。
在使用之前需要先擷取:
go get github.com/go-martini/martini
在indiepic.go
中引入martini
:
import ( "github.com/go-martini/martini")
定義一個結構體Results
用於表示輸出結果的資料結構:
type Results struct { Err int // 錯誤碼 Msg string // 錯誤資訊 Datas crawldata.ImageDatas // 資料,無資料時為nil}
因為需要輸出json
格式資料,所以需要用martini
的encoder
中介軟體資源,使用下面命令擷取:
go get github.com/martini-contrib/encoder
然後import
:
import ( "github.com/martini-contrib/encoder")
因為資料已經抓取完存入資料庫了,所以在main
函數中,就不在需要調用crawldata.Crawl()
了,將其注釋掉。然後編寫如下代碼:
func main() { // 使用crawldata包裡面的Crawl()抓取需要的資料存到資料庫 // crawldata.Crawl() m := martini.New() route := martini.NewRouter() var ( results Results err error ) m.Use(func(c martini.Context, w http.ResponseWriter, r *http.Request) { // 將encoder.JsonEncoder{}按照encoder.Encoder介面(注意大小寫)類型注入到內部 c.MapTo(encoder.JsonEncoder{}, (*encoder.Encoder)(nil)) w.Header().Set("Content-Type", "application/json; charset=utf-8") }) route.Get("/", func(enc encoder.Encoder) (int, []byte) { result := Results{10001, "Not Found Data", nil} return http.StatusOK, encoder.Must(enc.Encode(result)) }) route.Get("/api", func(enc encoder.Encoder) (int, []byte) { results.Datas, err = crawldata.GetAllImages() if err != nil { fmt.Println(s.Join([]string{"擷取資料失敗", err.Error()}, "-->")) result := Results{10001, "Data Error", nil} return http.StatusOK, encoder.Must(enc.Encode(result)) } else { results.Err = 10001 results.Msg = "擷取資料成功" return http.StatusOK, encoder.Must(enc.Encode(results)) } }) m.Action(route.Handle) m.Run()}
import
部分:
import ( "fmt" "github.com/go-martini/martini" "github.com/martini-contrib/encoder" "indiepic/crawldata" "net/http" s "strings")
然後運行:
go run indiepic.go
在瀏覽器中訪問 http://127.0.0.1:3000/api 即可看到輸出的json
資料。如果安裝了postman
可以使用postman
訪問地址,查看時選擇json
。
到這裡這個例子就結束了。源碼見GitHub。