新聞中心
一、數(shù)據(jù)結構
查詢結果的數(shù)據(jù)結構如下:

創(chuàng)新互聯(lián)建站長期為上千家客戶提供的網(wǎng)站建設服務,團隊從業(yè)經驗10年,關注不同地域、不同群體,并針對不同對象提供差異化的產品和服務;打造開放共贏平臺,與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為和碩企業(yè)提供專業(yè)的成都網(wǎng)站設計、成都網(wǎng)站建設,和碩網(wǎng)站改版等技術服務。擁有十多年豐富建站經驗和眾多成功案例,為您定制開發(fā)。
type Value = *gvar.Var // 返回數(shù)據(jù)表記錄值
type Record map[string]Value // 返回數(shù)據(jù)表記錄鍵值對
type Result []Record // 返回數(shù)據(jù)表記錄列表- ?
Value/Record/Result?用于?ORM?操作的結果數(shù)據(jù)類型。 - ?
Result?表示數(shù)據(jù)表記錄列表,?Record?表示一條數(shù)據(jù)表記錄,?Value?表示記錄中的一條鍵值數(shù)據(jù)。 - ?
Value?是?*gvar.Var?類型的別名類型,方便于后續(xù)的數(shù)據(jù)類型轉換。
二、Record數(shù)據(jù)記錄
接口文檔: https://pkg.GO.dev/github.com/gogf/gf/v2/database/gdb
?gdb?為數(shù)據(jù)表記錄操作提供了極高的靈活性和簡便性,除了支持以?map?的形式訪問/操作數(shù)據(jù)表記錄以外,也支持將數(shù)據(jù)表記錄轉換為?struct?進行處理。我們以下使用一個簡單的示例來演示該特性。
首先,我們的用戶表結構是這樣的(簡單設計的示例表):
CREATE TABLE `user` (
`uid` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(30) NOT NULL DEFAULT '' COMMENT '昵稱',
`site` varchar(255) NOT NULL DEFAULT '' COMMENT '主頁',
PRIMARY KEY (`uid`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;其次,我們的表數(shù)據(jù)如下:
uid name site
1 john https://GoFrame.org最后,我們的示例程序如下:
package main
import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gctx"
)
type User struct {
Uid int
Name string
}
func main() {
var (
user *User
ctx = gctx.New()
)
err := g.DB().Model("user").Where("uid", 1).Scan(&user)
if err != nil {
g.Log().Header(false).Fatal(ctx, err)
}
if user != nil {
g.Log().Header(false).Print(ctx, user)
}
}執(zhí)行后,輸出結果為:
{"Uid":1,"Name":"john"}這里,我們自定義了一個?struct?,里面只包含了?Uid?和?Name?屬性,可以看到它的屬性并不和數(shù)據(jù)表的字段一致,這也是?ORM?靈活的特性之一:支持指定屬性獲取。
通過?gdb.Model.Scan?方法可以將查詢到的數(shù)據(jù)記錄轉換為?struct?對象或者?struct?對象數(shù)組。由于這里傳遞的參數(shù)為?&user?即?**User?類型,那么將會轉換為一個?struct?對象,如果傳遞為?[]*User?類型的參數(shù),將會轉換為數(shù)組結果。
屬性字段映射規(guī)則:
需要注意的是,?map?中的鍵名為?uid?,?name?,?site?,而?struct?中的屬性為?Uid?,?Name?,那么他們之間是如何執(zhí)行映射的呢?主要是以下幾點簡單的規(guī)則:
- ?
struct?中需要匹配的屬性必須為公開屬性(首字母大寫); - 記錄結果中鍵名會自動按照 不區(qū)分大小寫 且 忽略?
-?/?_?/空格符號的形式與?struct?屬性進行匹配; - 如果匹配成功,那么將鍵值賦值給屬性,如果無法匹配,那么忽略該鍵值;
以下是幾個匹配的示例:
記錄鍵名 struct屬性 是否匹配
name Name match
Email Email match
nickname NickName match
NICKNAME NickName match
Nick-Name NickName match
nick_name NickName match
nick_name Nick_Name match
NickName Nick_Name match
Nick-Name Nick_Name match由于數(shù)據(jù)庫結果集轉?struct?的底層是依靠?gconv.Struct?方法實現(xiàn)的。
三、Result數(shù)據(jù)集合
?Result/Record?數(shù)據(jù)類型根據(jù)數(shù)據(jù)結果集操作的需要,往往需要根據(jù)記錄中特定的字段作為鍵名進行數(shù)據(jù)檢索,因此它包含多個用于轉換?Map/List?的方法,同時也包含了常用數(shù)據(jù)結構?JSON/XML?的轉換方法。
接口文檔: https://pkg.go.dev/github.com/gogf/gf/v2/database/gdb
由于方法比較簡單,這里便不再舉例說明。需要注意的是兩個方法?Record.Map?及?Result.List?,這兩個方法也是使用比較頻繁的方法,用以將?ORM?查詢結果信息轉換為可做展示的數(shù)據(jù)類型。由于結果集字段值底層為?[]byt?e類型,雖然使用了新的?Value?類型做了封裝,并且也提供了數(shù)十種常見的類型轉換方法,但是大多數(shù)時候需要直接將結果?Result?或者?Record?直接作為?json?或者?xml?數(shù)據(jù)結構返回,就需要做轉換才行。
使用示例:
package main
import (
"database/sql"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gctx"
)
type User struct {
Uid int
Name string
Site string
}
func main() {
var (
user []*User
ctx = gctx.New()
)
err := g.DB().Model("user").Where("uid", 1).Scan(&user)
if err != nil && err != sql.ErrNoRows {
g.Log().Header(false).Fatal(ctx, err)
}
if user != nil {
g.Log().Header(false).Print(ctx, user)
}
}執(zhí)行后,輸出結果為:
[{"Uid":1,"Name":"john","Site":"https://goframe.org"}]四、結果為空判斷
使用?gf ORM?對返回結果為空判斷非常簡便,大部分場景下直接判斷返回的數(shù)據(jù)是否為?nil?或者長度為?0?,或者使用?IsEmpty/IsNil?方法。
數(shù)據(jù)集合
r, err := g.Model("order").Where("status", 1).All()
if err != nil {
return err
}
if len(r) == 0 {
// 結果為空
}也可以使用?IsEmpty?方法:
r, err := g.Model("order").Where("status", 1).All()
if err != nil {
return err
}
if r.IsEmpty() {
// 結果為空
}數(shù)據(jù)記錄
r, err := g.Model("order").Where("status", 1).One()
if err != nil {
return err
}
if len(r) == 0 {
// 結果為空
}也可以使用?IsEmpty?方法:
r, err := g.Table("order").Where("status", 1).One()
if err != nil {
return err
}
if r.IsEmpty() {
// 結果為空
}數(shù)據(jù)字段值
返回的是一個"泛型"變量,這個只能使用?IsEmpty?來判斷是否為空了。
r, err := g.Model("order").Where("status", 1).Value()
if err != nil {
return err
}
if r.IsEmpty() {
// 結果為空
}字段值數(shù)組
查詢返回字段值數(shù)組本身類型為?[]gdb.Value?類型,因此直接判斷長度是否為?0?即可。
// Array/FindArray
r, err := g.Table("order").Fields("id").Where("status", 1).Array()
if err != nil {
return err
}
if len(r) == 0 {
// 結果為空
}struct對象
關于?Struct?轉換對象來說會有一點不一樣,我們直接看例子吧。
當傳遞的對象本身就是一個空指針時,如果查詢到數(shù)據(jù),那么會在內部自動創(chuàng)建這個對象;如果沒有查詢到數(shù)據(jù),那么這個空指針仍舊是一個空指針,內部并不會做任何處理。
var user *User
err := g.Model("order").Where("status", 1).Scan(&user)
if err != nil {
return err
}
if user == nil {
// 結果為空
}當傳遞的對象本身已經是一個初始化的對象,如果查詢到數(shù)據(jù),那么會在內部將數(shù)據(jù)賦值給這個對象;如果沒有查詢到數(shù)據(jù),那么此時就沒辦法將對象做?nil?判斷空結果。因此?ORM?會返回一個?sql.ErrNoRows?錯誤,提醒開發(fā)者沒有查詢到任何數(shù)據(jù)并且對象沒有做任何賦值,對象的所有屬性還是給定的初始化數(shù)值,以便開發(fā)者可以做進一步的空結果判斷。
var user = new(User)
err := g.Model("order").Where("status", 1).Scan(&user)
if err != nil && err != sql.ErrNoRows {
return err
}
if err == sql.ErrNoRows {
// 結果為空
}所以我們推薦開發(fā)者不要傳遞一個初始化過后的對象給?ORM?,而是直接傳遞一個對象的指針的指針類型(?**struct?類型),?ORM?內部會根據(jù)查詢結果智能地做自動初始化。
struct數(shù)組
當傳遞的對象數(shù)組本身是一個空數(shù)組(長度為0),如果查詢到數(shù)據(jù),那么會在內部自動賦值給數(shù)組;如果沒有查詢到數(shù)據(jù),那么這個空數(shù)組仍舊是一個空數(shù)組,內部并不會做任何處理。
var users []*User
err := g.Model("order").Where("status", 1).Scan(&users)
if err != nil {
return err
}
if len(users) == 0 {
// 結果為空
}當傳遞的對象數(shù)組本身不是空數(shù)組,如果查詢到數(shù)據(jù),那么會在內部自動從索引0位置覆蓋到數(shù)組上;如果沒有查詢到數(shù)據(jù),那么此時就沒辦法將數(shù)組做長度為0判斷空結果。因此?ORM?會返回一個?sql.ErrNoRows?錯誤,提醒開發(fā)者沒有查詢到任何數(shù)據(jù)并且數(shù)組沒有做任何賦值,以便開發(fā)者可以做進一步的空結果判斷。
var users = make([]*User, 100)
err := g.Model("order").Where("status", 1).Scan(&users)
if err != nil {
return err
}
if err == sql.ErrNoRows {
// 結果為空
} 標題名稱:創(chuàng)新互聯(lián)GoFrame教程:GoFrame數(shù)據(jù)庫ORM-結果處理
URL地址:http://m.fisionsoft.com.cn/article/cdggpeg.html


咨詢
建站咨詢
