按值傳遞函數(shù)參數(shù),是拷貝參數(shù)的實(shí)際值到函數(shù)的形式參數(shù)的方法調(diào)用。在這種情況下,參數(shù)在函數(shù)內(nèi)變化對(duì)參數(shù)不會(huì)有影響。
創(chuàng)新互聯(lián)公司公司2013年成立,先為平谷等服務(wù)建站,平谷等地企業(yè),進(jìn)行企業(yè)商務(wù)咨詢(xún)服務(wù)。為平谷企業(yè)網(wǎng)站制作PC+手機(jī)+微官網(wǎng)三網(wǎng)同步一站式服務(wù)解決您的所有建站問(wèn)題。
默認(rèn)情況下,Go編程語(yǔ)言使用調(diào)用通過(guò)值的方法來(lái)傳遞參數(shù)。在一般情況下,這意味著,在函數(shù)內(nèi)碼不能改變用來(lái)調(diào)用所述函數(shù)的參數(shù)。考慮函數(shù)swap()的定義如下。
代碼如下:
/* function definition to swap the values */
func swap(int x, int y) int {
var temp int
temp = x /* save the value of x */
x = y /* put y into x */
y = temp /* put temp into y */
return temp;
}
現(xiàn)在,讓我們通過(guò)使實(shí)際值作為在以下示例調(diào)用函數(shù)swap():
代碼如下:
package main
import "fmt"
func main() {
/* local variable definition */
var a int = 100
var b int = 200
fmt.Printf("Before swap, value of a : %d\n", a )
fmt.Printf("Before swap, value of b : %d\n", b )
/* calling a function to swap the values */
swap(a, b)
fmt.Printf("After swap, value of a : %d\n", a )
fmt.Printf("After swap, value of b : %d\n", b )
}
func swap(x, y int) int {
var temp int
temp = x /* save the value of x */
x = y /* put y into x */
y = temp /* put temp into y */
return temp;
}
讓我們把上面的代碼放在一個(gè)C文件,編譯并執(zhí)行它,它會(huì)產(chǎn)生以下結(jié)果:
Before swap, value of a :100
Before swap, value of b :200
After swap, value of a :100
After swap, value of b :200
這表明,參數(shù)值沒(méi)有被改變,雖然它們已經(jīng)在函數(shù)內(nèi)部改變。
通過(guò)傳遞函數(shù)參數(shù),即是拷貝參數(shù)的地址到形式參數(shù)的參考方法調(diào)用。在函數(shù)內(nèi)部,地址是訪問(wèn)調(diào)用中使用的實(shí)際參數(shù)。這意味著,對(duì)參數(shù)的更改會(huì)影響傳遞的參數(shù)。
要通過(guò)引用傳遞的值,參數(shù)的指針被傳遞給函數(shù)就像任何其他的值。所以,相應(yīng)的,需要聲明函數(shù)的參數(shù)為指針類(lèi)型如下面的函數(shù)swap(),它的交換兩個(gè)整型變量的值指向它的參數(shù)。
代碼如下:
/* function definition to swap the values */
func swap(x *int, y *int) {
var temp int
temp = *x /* save the value at address x */
*x = *y /* put y into x */
*y = temp /* put temp into y */
}
現(xiàn)在,讓我們調(diào)用函數(shù)swap()通過(guò)引用作為在下面的示例中傳遞數(shù)值:
代碼如下:
package main
import "fmt"
func main() {
/* local variable definition */
var a int = 100
var b int= 200
fmt.Printf("Before swap, value of a : %d\n", a )
fmt.Printf("Before swap, value of b : %d\n", b )
/* calling a function to swap the values.
* a indicates pointer to a ie. address of variable a and
* b indicates pointer to b ie. address of variable b.
*/
swap(a, b)
fmt.Printf("After swap, value of a : %d\n", a )
fmt.Printf("After swap, value of b : %d\n", b )
}
func swap(x *int, y *int) {
var temp int
temp = *x /* save the value at address x */
*x = *y /* put y into x */
*y = temp /* put temp into y */
}
讓我們把上面的代碼放在一個(gè)C文件,編譯并執(zhí)行它,它會(huì)產(chǎn)生以下結(jié)果:
Before swap, value of a :100
Before swap, value of b :200
After swap, value of a :200
After swap, value of b :100
這表明變化的功能以及不同于通過(guò)值調(diào)用的外部體現(xiàn)的改變不能反映函數(shù)之外。
在以下這段代碼中,我們操作一個(gè)文件,無(wú)論成功與否都需要關(guān)閉文件句柄。這里在三處不同的位置都調(diào)用了file.Close()方法,代碼顯得非常冗余。
我們利用延遲調(diào)用來(lái)優(yōu)化代碼。定義后的defer代碼,會(huì)在return之前返回,讓代碼顯得更加緊湊,且可讀性變強(qiáng),對(duì)上面的代碼改造如下:
我們通過(guò)這個(gè)示例來(lái)看一下延遲調(diào)用與正常代碼之間的執(zhí)行順序
先簡(jiǎn)單分析一下代碼邏輯:
從輸出中,我們可以觀察到如下現(xiàn)象:
從這個(gè)實(shí)例中,我們很明顯觀察到,defer語(yǔ)句是在return之前執(zhí)行
如果一個(gè)函數(shù)內(nèi)定義了多個(gè)defer,則調(diào)用順序?yàn)長(zhǎng)IFO(后進(jìn)先出)方式執(zhí)行。
仍然是相同的例子,但是在TestDefer中我們定義了三個(gè)defer輸出,根據(jù)LIFO原則,輸出的順序是3rd-2nd-1st,根據(jù)最后的結(jié)果,也是逆向向上執(zhí)行defer輸出。
就在整理這篇筆記的時(shí)候,發(fā)現(xiàn)了自己的認(rèn)知誤區(qū),主要是本節(jié)實(shí)例三中發(fā)現(xiàn)的,先來(lái)看一下英文的描述:
對(duì)于上面的這段話(huà)的理解:
下面是代碼執(zhí)行輸出,我們來(lái)一起分析一下:
雖然在a()函數(shù)內(nèi),顯示的返回了10,但是main函數(shù)中得到的結(jié)果是defer函數(shù)自增后的結(jié)果,我們來(lái)分析一下代碼:
在這篇文章的上一版,我曾經(jīng)嘗試用指針取解釋defer修改返回值的類(lèi)型,但是感覺(jué)不夠透徹,也讓閱讀者非常困惑,索性參考了一下go官方blog中的一篇文章,在此基礎(chǔ)上進(jìn)行了擴(kuò)展。如需要閱讀原文,可以參考下面的文章。
智能合約調(diào)用是實(shí)現(xiàn)一個(gè) DApp 的關(guān)鍵,一個(gè)完整的 DApp 包括前端、后端、智能合約及區(qū)塊 鏈系統(tǒng),智能合約的調(diào)用是連接區(qū)塊鏈與前后端的關(guān)鍵。
我們先來(lái)了解一下智能合約調(diào)用的基礎(chǔ)原理。智能合約運(yùn)行在以太坊節(jié)點(diǎn)的 EVM 中。因此要 想調(diào)用合約必須要訪問(wèn)某個(gè)節(jié)點(diǎn)。
以后端程序?yàn)槔?,后端服?wù)若想連接節(jié)點(diǎn)有兩種可能,一種是雙 方在同一主機(jī),此時(shí)后端連接節(jié)點(diǎn)可以采用 本地 IPC(Inter-Process Communication,進(jìn) 程間通信)機(jī)制,也可以采用 RPC(Remote Procedure Call,遠(yuǎn)程過(guò)程調(diào)用)機(jī)制;另 一種情況是雙方不在同一臺(tái)主機(jī),此時(shí)只能采用 RPC 機(jī)制進(jìn)行通信。
提到 RPC, 讀者應(yīng)該對(duì) Geth 啟動(dòng)參數(shù)有點(diǎn)印象,Geth 啟動(dòng)時(shí)可以選擇開(kāi)啟 RPC 服務(wù),對(duì)應(yīng)的 默認(rèn)服務(wù)端口是 8545。。
接著,我們來(lái)了解一下智能合約運(yùn)行的過(guò)程。
智能合約的運(yùn)行過(guò)程是后端服務(wù)連接某節(jié)點(diǎn),將 智能合約的調(diào)用(交易)發(fā)送給節(jié)點(diǎn),節(jié)點(diǎn)在驗(yàn)證了交易的合法性后進(jìn)行全網(wǎng)廣播,被礦工打包到 區(qū)塊中代表此交易得到確認(rèn),至此交易才算完成。
就像數(shù)據(jù)庫(kù)一樣,每個(gè)區(qū)塊鏈平臺(tái)都會(huì)提供主流 開(kāi)發(fā)語(yǔ)言的 SDK(Software Development Kit,軟件開(kāi)發(fā)工具包),由于 Geth 本身就是用 Go 語(yǔ)言 編寫(xiě)的,因此若想使用 Go 語(yǔ)言連接節(jié)點(diǎn)、發(fā)交易,直接在工程內(nèi)導(dǎo)入 go-ethereum(Geth 源碼) 包就可以了,剩下的問(wèn)題就是流程和 API 的事情了。
總結(jié)一下,智能合約被調(diào)用的兩個(gè)關(guān)鍵點(diǎn)是節(jié)點(diǎn)和 SDK。
由于 IPC 要求后端與節(jié)點(diǎn)必須在同一主機(jī),所以很多時(shí)候開(kāi)發(fā)者都會(huì)采用 RPC 模式。除了 RPC,以太坊也為開(kāi)發(fā)者提供了 json- rpc 接口,本文就不展開(kāi)討論了。
接下來(lái)介紹如何使用 Go 語(yǔ)言,借助 go-ethereum 源碼庫(kù)來(lái)實(shí)現(xiàn)智能合約的調(diào)用。這是有固定 步驟的,我們先來(lái)說(shuō)一下總體步驟,以下面的合約為例。
步驟 01:編譯合約,獲取合約 ABI(Application Binary Interface,應(yīng)用二進(jìn)制接口)。 單擊【ABI】按鈕拷貝合約 ABI 信息,將其粘貼到文件 calldemo.abi 中(可使用 Go 語(yǔ)言IDE 創(chuàng)建該文件,文件名可自定義,后綴最好使用 abi)。
最好能將 calldemo.abi 單獨(dú)保存在一個(gè)目錄下,輸入“l(fā)s”命令只能看到 calldemo.abi 文件,參 考效果如下:
步驟 02:獲得合約地址。注意要將合約部署到 Geth 節(jié)點(diǎn)。因此 Environment 選擇為 Web3 Provider。
在【Environment】選項(xiàng)框中選擇“Web3 Provider”,然后單擊【Deploy】按鈕。
部署后,獲得合約地址為:0xa09209c28AEf59a4653b905792a9a910E78E7407。
步驟 03:利用 abigen 工具(Geth 工具包內(nèi)的可執(zhí)行程序)編譯智能合約為 Go 代碼。abigen 工具的作用是將 abi 文件轉(zhuǎn)換為 Go 代碼,命令如下:
其中各參數(shù)的含義如下。 (1)abi:是指定傳入的 abi 文件。 (2)type:是指定輸出文件中的基本結(jié)構(gòu)類(lèi)型。 (3)pkg:指定輸出文件 package 名稱(chēng)。 (4)out:指定輸出文件名。 執(zhí)行后,將在代碼目錄下看到 funcdemo.go 文件,讀者可以打開(kāi)該文件欣賞一下,注意不要修改它。
步驟 04:創(chuàng)建 main.go,填入如下代碼。 注意代碼中 HexToAddress 函數(shù)內(nèi)要傳入該合約部署后的地址,此地址在步驟 01 中獲得。
步驟 04:設(shè)置 go mod,以便工程自動(dòng)識(shí)別。
前面有所提及,若要使用 Go 語(yǔ)言調(diào)用智能合約,需要下載 go-ethereum 工程,可以使用下面 的指令:
該指令會(huì)自動(dòng)將 go-ethereum 下載到“$GOPATH/src/github點(diǎn)抗 /ethereum/go-ethereum”,這樣還算 不錯(cuò)。不過(guò),Go 語(yǔ)言自 1.11 版本后,增加了 module 管理工程的模式。只要設(shè)置好了 go mod,下載 依賴(lài)工程的事情就不必關(guān)心了。
接下來(lái)設(shè)置 module 生效和 GOPROXY,命令如下:
在項(xiàng)目工程內(nèi),執(zhí)行初始化,calldemo 可以自定義名稱(chēng)。
步驟 05:運(yùn)行代碼。執(zhí)行代碼,將看到下面的效果,以及最終輸出的 2020。
上述輸出信息中,可以看到 Go 語(yǔ)言會(huì)自動(dòng)下載依賴(lài)文件,這就是 go mod 的神奇之處??吹?2020,相信讀者也知道運(yùn)行結(jié)果是正確的了。
本文主要介紹了Go語(yǔ)言中文件讀寫(xiě)的相關(guān)操作。
文件是什么?
計(jì)算機(jī)中的文件是存儲(chǔ)在外部介質(zhì)(通常是磁盤(pán))上的數(shù)據(jù)集合,文件分為文本文件和二進(jìn)制文件。
os.Open() 函數(shù)能夠打開(kāi)一個(gè)文件,返回一個(gè) *File 和一個(gè) err 。對(duì)得到的文件實(shí)例調(diào)用 close() 方法能夠關(guān)閉文件。
為了防止文件忘記關(guān)閉,我們通常使用defer注冊(cè)文件關(guān)閉語(yǔ)句。
Read方法定義如下:
它接收一個(gè)字節(jié)切片,返回讀取的字節(jié)數(shù)和可能的具體錯(cuò)誤,讀到文件末尾時(shí)會(huì)返回 0 和 io.EOF 。 舉個(gè)例子:
使用for循環(huán)讀取文件中的所有數(shù)據(jù)。
bufio是在file的基礎(chǔ)上封裝了一層API,支持更多的功能。
io/ioutil 包的 ReadFile 方法能夠讀取完整的文件,只需要將文件名作為參數(shù)傳入。
os.OpenFile() 函數(shù)能夠以指定模式打開(kāi)文件,從而實(shí)現(xiàn)文件寫(xiě)入相關(guān)功能。
其中:
name :要打開(kāi)的文件名 flag :打開(kāi)文件的模式。 模式有以下幾種:
perm :文件權(quán)限,一個(gè)八進(jìn)制數(shù)。r(讀)04,w(寫(xiě))02,x(執(zhí)行)01。
分享標(biāo)題:go語(yǔ)言調(diào)用jqva go語(yǔ)言調(diào)用打印機(jī)
鏈接分享:http://www.rwnh.cn/article12/ddjcgdc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站設(shè)計(jì)、外貿(mào)建站、App開(kāi)發(fā)、微信小程序、動(dòng)態(tài)網(wǎng)站、網(wǎng)站營(yíng)銷(xiāo)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)