在本節(jié)中,您將使用 Go 執(zhí)行 SQL INSERT語(yǔ)句以向數(shù)據(jù)庫(kù)添加新行。
在曹妃甸等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強(qiáng)發(fā)展的系統(tǒng)性、市場(chǎng)前瞻性、產(chǎn)品創(chuàng)新能力,以專(zhuān)注、極致的服務(wù)理念,為客戶(hù)提供網(wǎng)站建設(shè)、成都網(wǎng)站建設(shè) 網(wǎng)站設(shè)計(jì)制作定制設(shè)計(jì),公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),品牌網(wǎng)站建設(shè),成都全網(wǎng)營(yíng)銷(xiāo),外貿(mào)網(wǎng)站建設(shè),曹妃甸網(wǎng)站建設(shè)費(fèi)用合理。
您已經(jīng)了解了如何使用Query和QueryRow處理返回?cái)?shù)據(jù)的 SQL 語(yǔ)句。要執(zhí)行 不 返回?cái)?shù)據(jù)的 SQL 語(yǔ)句,請(qǐng)使用Exec.
1、在albumByID下面,粘貼以下addAlbum函數(shù)以在數(shù)據(jù)庫(kù)中插入新專(zhuān)輯,然后保存 main.go。
在此代碼中:
(1)用DB.Exec執(zhí)行INSERT語(yǔ)句。
Exec接受一條 SQL 語(yǔ)句,后跟 SQL 語(yǔ)句的參數(shù)值。
(2)檢查嘗試INSERT中的錯(cuò)誤。
(3)使用Result.LastInsertId檢索插入的數(shù)據(jù)庫(kù)行的 ID 。
(4)檢查嘗試檢索 ID 的錯(cuò)誤。
2、更新main以調(diào)用新addAlbum函數(shù)。
在main函數(shù)末尾添加以下代碼。
在新代碼中:
(1)調(diào)用addAlbum添加新專(zhuān)輯,將要添加的專(zhuān)輯的 ID 分配給albID變量。
從包含 main.go 目錄的命令行中,運(yùn)行代碼。
恭喜!您剛剛使用 Go 對(duì)關(guān)系數(shù)據(jù)庫(kù)執(zhí)行了簡(jiǎn)單的操作。
本節(jié)包含您使用本教程構(gòu)建的應(yīng)用程序的代碼。
Go語(yǔ)言標(biāo)準(zhǔn)庫(kù)中提供了sort包對(duì)整型,浮點(diǎn)型,字符串型切片進(jìn)行排序,檢查一個(gè)切片是否排好序,使用二分法搜索函數(shù)在一個(gè)有序切片中搜索一個(gè)元素等功能。
關(guān)于sort包內(nèi)的函數(shù)說(shuō)明與使用,請(qǐng)查看
在這里簡(jiǎn)單講幾個(gè)sort包中常用的函數(shù)
在Go語(yǔ)言中,對(duì)字符串的排序都是按照字節(jié)排序,也就是說(shuō)在對(duì)字符串排序時(shí)是區(qū)分大小寫(xiě)的。
二分搜索算法
Go語(yǔ)言中提供了一個(gè)使用二分搜索算法的sort.Search(size,fn)方法:每次只需要比較㏒?n個(gè)元素,其中n為切片中元素的總數(shù)。
sort.Search(size,fn)函數(shù)接受兩個(gè)參數(shù):所處理的切片的長(zhǎng)度和一個(gè)將目標(biāo)元素與有序切片的元素相比較的函數(shù),該函數(shù)是一個(gè)閉包,如果該有序切片是升序排列,那么在判斷時(shí)使用 有序切片的元素 = 目標(biāo)元素。該函數(shù)返回一個(gè)int值,表示與目標(biāo)元素相同的切片元素的索引。
在切片中查找出某個(gè)與目標(biāo)字符串相同的元素索引
歡迎golang同胞!在本教程中,我們將研究如何在基于 Go 的程序中與 GraphQL 服務(wù)器進(jìn)行交互。在本教程結(jié)束時(shí),我們應(yīng)該知道如何執(zhí)行以下操作:
在本教程中,我們將專(zhuān)注于學(xué)習(xí) GraphQL 的數(shù)據(jù)檢索方面,并且我們將使用內(nèi)存中的數(shù)據(jù)源來(lái)支持它。這應(yīng)該為我們?cè)诤罄m(xù)教程的基礎(chǔ)上建立一個(gè)良好的基礎(chǔ)。
好的,所以在我們深入研究之前,我們應(yīng)該真正了解 GraphQL 的基礎(chǔ)知識(shí)。作為開(kāi)發(fā)人員,使用它對(duì)我們有什么好處?
好吧,考慮使用每天處理數(shù)十萬(wàn)甚至數(shù)百萬(wàn)請(qǐng)求的系統(tǒng)。傳統(tǒng)上,我們會(huì)使用位于數(shù)據(jù)庫(kù)前面的系統(tǒng) API,它會(huì)返回大量 JSON 響應(yīng),其中包含許多我們可能不一定需要的冗余信息。
如果我們正在處理大規(guī)模的應(yīng)用程序,發(fā)送冗余數(shù)據(jù)的成本可能會(huì)很高,并且由于有效負(fù)載大小會(huì)阻塞我們的網(wǎng)絡(luò)帶寬。
GraphQL基本上可以讓我們以減少噪音和描述數(shù)據(jù),我們希望讓我們的檢索,從我們的API中檢索 只有 我們需要為我們當(dāng)前的任務(wù)/視圖/不管。
這只是該技術(shù)為我們提供的眾多好處的一個(gè)例子。希望在接下來(lái)的教程系列中,我們會(huì)提前看到更多這些好處。
需要注意的重要一點(diǎn)是,GraphQL 不像我們傳統(tǒng)的 SQL 那樣是一種查詢(xún)語(yǔ)言。它是位于我們 API 前面的抽象, 不 依賴(lài)于任何特定的數(shù)據(jù)庫(kù)或存儲(chǔ)引擎。
這真的很酷。我們可以建立一個(gè)與現(xiàn)有服務(wù)商交互的 GraphQL 服務(wù)器,然后圍繞著這個(gè)新的 GraphQL 服務(wù)器構(gòu)建,而不必?fù)?dān)心修改現(xiàn)有的 REST API。
讓我們看看 RESTful 方法與 GraphQL 方法有何不同?,F(xiàn)在,假設(shè)我們正在構(gòu)建一個(gè)返回該站點(diǎn)上所有教程的服務(wù),如果我們想要特定教程的信息,我們通常會(huì)創(chuàng)建一個(gè) API 端點(diǎn),允許我們根據(jù) ID 檢索特定教程:
如果給定一個(gè) valid ID,這將返回一個(gè)響應(yīng),看起來(lái)像這樣:
現(xiàn)在,假設(shè)我們想創(chuàng)建一個(gè)小部件,列出該作者撰寫(xiě)的書(shū)籍 5 個(gè)帖子。我們可以點(diǎn)擊/author/:id端點(diǎn)以檢索該作者撰寫(xiě)的所有帖子,然后進(jìn)行后續(xù)調(diào)用以檢索前 5 個(gè)帖子中的每一個(gè)?;蛘?,我們可以制作一個(gè)全新的端點(diǎn)來(lái)為我們返回這些數(shù)據(jù)。
這兩種解決方案聽(tīng)起來(lái)都不是特別吸引人,因?yàn)樗鼈儠?huì)創(chuàng)建不需要的請(qǐng)求量或返回過(guò)多的數(shù)據(jù),這突出了 RESTful 方法開(kāi)始出現(xiàn)一些裂縫的地方。
這就是 GraphQL 發(fā)揮作用的地方。使用 GraphQL,我們可以定義我們希望在查詢(xún)中返回的數(shù)據(jù)的確切結(jié)構(gòu)。所以如果我們想要上面的信息,我們可以創(chuàng)建一個(gè)看起來(lái)像這樣的查詢(xún):
這將隨后返回我們的教程、該教程的作者和一組表示該作者編寫(xiě)的教程的教程 ID,而無(wú)需發(fā)送額外的 x 多個(gè) REST 請(qǐng)求來(lái)獲取信息!那有多好?
好的,現(xiàn)在我們對(duì) GraphQL 以及對(duì)它的用途有了更多的了解,讓我們?cè)趯?shí)踐中看看它。
我們將使用graphql-go/graphql實(shí)現(xiàn)在 Go 中創(chuàng)建一個(gè)簡(jiǎn)單的 GraphQL 服務(wù)器 。
讓我們首先使用go mod init以下方法初始化我們的項(xiàng)目:
接下來(lái),讓我們創(chuàng)建一個(gè)名為main.go. 我們將從簡(jiǎn)單開(kāi)始創(chuàng)建一個(gè)非常簡(jiǎn)單的 GraphQL 服務(wù)器,它具有一個(gè)非常簡(jiǎn)單的解析器:
現(xiàn)在,如果我們嘗試運(yùn)行它,讓我們看看會(huì)發(fā)生什么:
所以,如果一切正常,那么我們就可以設(shè)置一個(gè)非常簡(jiǎn)單的 GraphQL 服務(wù)器并對(duì)這個(gè)服務(wù)器進(jìn)行非常簡(jiǎn)單的查詢(xún)。
讓我們分解上面代碼中發(fā)生的事情,以便我們可以進(jìn)一步擴(kuò)展它。在lines 14-21我們定義我們的Schema. 當(dāng)我們對(duì)我們的 GraphQL API 進(jìn)行查詢(xún)時(shí),我們基本上定義了我們想要返回給我們的對(duì)象上的哪些字段,因此我們必須在我們的 Schema 重新定義這些字段。
在 上line 17,我們定義了一個(gè)解析器函數(shù),每當(dāng)field請(qǐng)求此特定內(nèi)容時(shí)就會(huì)觸發(fā)該解析器函數(shù)?,F(xiàn)在,我們只是返回字符串 "world",但我們將實(shí)現(xiàn)從這里查詢(xún)數(shù)據(jù)庫(kù)的能力。
讓我們看一下main.go文件的第二部分。在line 30我們開(kāi)始定義query請(qǐng)求領(lǐng)域hello。
然后我們創(chuàng)建一個(gè)params結(jié)構(gòu),其中包含對(duì)我們定義的Schema以及我們的RequestString請(qǐng)求的引用 。
最后,在line 36我們執(zhí)行請(qǐng)求并將請(qǐng)求的結(jié)果填充到r. 然后我們進(jìn)行一些錯(cuò)誤處理,然后將響應(yīng)編組為 JSON 并將其打印到我們的控制臺(tái)上。
現(xiàn)在我們已經(jīng)啟動(dòng)并運(yùn)行了一個(gè)非常簡(jiǎn)單的 GraphQL 服務(wù)器,并且我們能夠?qū)ζ溥M(jìn)行查詢(xún),讓我們更進(jìn)一步,構(gòu)建一個(gè)更復(fù)雜的示例。
我們將創(chuàng)建一個(gè) GraphQL 服務(wù)器,它返回一系列內(nèi)存中的教程及其作者,以及對(duì)這些特定教程的任何評(píng)論。
讓我們定義一些struct代表 a Tutorial、 anAuthor和 a 的's Comment:
然后我們可以創(chuàng)建一個(gè)非常簡(jiǎn)單的populate()函數(shù),它將返回一個(gè)類(lèi)型數(shù)組Tutorial:
這將為我們提供一個(gè)簡(jiǎn)單的教程列表,然后我們可以稍后解決。
我們將從使用 GraphQL 創(chuàng)建一個(gè)新對(duì)象開(kāi)始graphql.NewObject()。我們將使用 GraphQL 的嚴(yán)格類(lèi)型定義 3 種不同的類(lèi)型,它們將與structs我們已經(jīng)定義的 3 種相匹配。
我們的Commentstruct 可以說(shuō)是最簡(jiǎn)單的,它只包含一個(gè) string Body,所以我們可以commentType很容易地將其表示為:
接下來(lái),我們將處理該Author結(jié)構(gòu)并將其定義為一個(gè)新的 graphql.NewObject(). 這會(huì)稍微復(fù)雜一些,因?yàn)樗扔幸粋€(gè) String字段,也有一個(gè)Int值列表,這些值代表他們編寫(xiě)的教程的 ID。
最后,讓我們定義我們的tutorialTypewhich 將封裝 an author和comment's的數(shù)組以及 anID和 a title:
現(xiàn)在我們已經(jīng)定義了我們的Type系統(tǒng),讓我們著手更新我們的 Schema 以反映這些新類(lèi)型。我們將定義 2 個(gè) distinct Field,第一個(gè)將是我們的tutorial字段,它允許我們Tutorials 根據(jù)傳入查詢(xún)的 ID檢索個(gè)人。第二個(gè)將是一個(gè)list字段,它將允許我們檢索Tutorials我們?cè)趦?nèi)存中定義的完整數(shù)組。
所以我們已經(jīng)創(chuàng)建了我們的類(lèi)型并更新了我們的 GraphQL 模式,我們做得還不錯(cuò)!
讓我們嘗試使用我們的新 GraphQL 服務(wù)器并處理我們提交的查詢(xún)。讓我們來(lái)嘗試我們的list架構(gòu)改變query ,我們已經(jīng)在我們得到main()的功能:
讓我們分解一下。所以在我們的查詢(xún)中,我們有一個(gè)特殊的root對(duì)象。然后我們?cè)谄渲姓f(shuō)我們想要該list對(duì)象上的字段。在返回的名單list,我們希望看到的id,title,comments和 author。
當(dāng)我們運(yùn)行它時(shí),我們應(yīng)該會(huì)看到以下輸出:
正如我們所見(jiàn),我們的查詢(xún)以 JSON 格式返回了我們所有的教程,看起來(lái)非常像我們初始查詢(xún)的結(jié)構(gòu)。
現(xiàn)在讓我們嘗試對(duì)我們的tutorial模式進(jìn)行查詢(xún):
再一次,當(dāng)我們運(yùn)行它時(shí),我們應(yīng)該看到它已經(jīng)成功地檢索了內(nèi)存中的單獨(dú)教程ID=1:
完美,看起來(lái)我們已經(jīng)讓list我們的tutorial模式和我們的模式都按預(yù)期工作了。
這就是我們將在這個(gè)初始教程中介紹的全部?jī)?nèi)容。我們已經(jīng)成功地設(shè)置了一個(gè)簡(jiǎn)單的 GraphQL 服務(wù)器,該服務(wù)器由內(nèi)存數(shù)據(jù)存儲(chǔ)支持。
在下一個(gè)教程中,我們將研究 GraphQL 突變并更改我們的數(shù)據(jù)源以使用 SQL 數(shù)據(jù)庫(kù)
Go里面提供了一個(gè)關(guān)鍵字select,通過(guò)select可以監(jiān)聽(tīng)channel上的數(shù)據(jù)流動(dòng)。
select的用法與switch語(yǔ)言非常類(lèi)似,由select開(kāi)始一個(gè)新的選擇塊,每個(gè)選擇條件由case語(yǔ)句來(lái)描述。
與switch語(yǔ)句相比, select有比較多的限制,其中最大的一條限制就是每個(gè)case語(yǔ)句里必須是一個(gè)IO操作,大致的結(jié)構(gòu)如下:
在一個(gè)select語(yǔ)句中,Go語(yǔ)言會(huì)按順序從頭至尾評(píng)估每一個(gè)發(fā)送和接收的語(yǔ)句。
如果其中的任意一語(yǔ)句可以繼續(xù)執(zhí)行(即沒(méi)有被阻塞),那么就從那些可以執(zhí)行的語(yǔ)句中任意選擇一條來(lái)使用。
如果沒(méi)有任意一條語(yǔ)句可以執(zhí)行(即所有的通道都被阻塞),那么有兩種可能的情況:
如果給出了default語(yǔ)句,那么就會(huì)執(zhí)行default語(yǔ)句,同時(shí)程序的執(zhí)行會(huì)從select語(yǔ)句后的語(yǔ)句中恢復(fù)。
如果沒(méi)有default語(yǔ)句,那么select語(yǔ)句將被阻塞,直到至少有一個(gè)通信可以進(jìn)行下去
有時(shí)候會(huì)出現(xiàn)goroutine阻塞的情況,那么我們?nèi)绾伪苊庹麄€(gè)程序進(jìn)入阻塞的情況呢?我們可以利用select來(lái)設(shè)置超時(shí),通過(guò)如下的方式實(shí)現(xiàn):
select總結(jié):
作用: 用來(lái)監(jiān)聽(tīng) channel 上的數(shù)據(jù)流動(dòng)方向。 讀?寫(xiě)?
select實(shí)現(xiàn)fibonacci數(shù)列: