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

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


咨詢
建站咨詢
