bl双性强迫侵犯h_国产在线观看人成激情视频_蜜芽188_被诱拐的少孩全彩啪啪漫画

go語言執行代碼的函數 go執行js代碼

3.6 Go語言函數的延遲調用(Deferred Code)

在以下這段代碼中,我們操作一個文件,無論成功與否都需要關閉文件句柄。這里在三處不同的位置都調用了file.Close()方法,代碼顯得非常冗余。

創新互聯公司專注于撫州網站建設服務及定制,我們擁有豐富的企業做網站經驗。 熱誠為您提供撫州營銷型網站建設,撫州網站制作、撫州網頁設計、撫州網站官網定制、微信小程序服務,打造撫州網絡公司原創品牌,更為您提供撫州網站排名全網營銷落地服務。

我們利用延遲調用來優化代碼。定義后的defer代碼,會在return之前返回,讓代碼顯得更加緊湊,且可讀性變強,對上面的代碼改造如下:

我們通過這個示例來看一下延遲調用與正常代碼之間的執行順序

先簡單分析一下代碼邏輯:

從輸出中,我們可以觀察到如下現象:

從這個實例中,我們很明顯觀察到,defer語句是在return之前執行

如果一個函數內定義了多個defer,則調用順序為LIFO(后進先出)方式執行。

仍然是相同的例子,但是在TestDefer中我們定義了三個defer輸出,根據LIFO原則,輸出的順序是3rd-2nd-1st,根據最后的結果,也是逆向向上執行defer輸出。

就在整理這篇筆記的時候,發現了自己的認知誤區,主要是本節實例三中發現的,先來看一下英文的描述:

對于上面的這段話的理解:

下面是代碼執行輸出,我們來一起分析一下:

雖然在a()函數內,顯示的返回了10,但是main函數中得到的結果是defer函數自增后的結果,我們來分析一下代碼:

在這篇文章的上一版,我曾經嘗試用指針取解釋defer修改返回值的類型,但是感覺不夠透徹,也讓閱讀者非常困惑,索性參考了一下go官方blog中的一篇文章,在此基礎上進行了擴展。如需要閱讀原文,可以參考下面的文章。

go語言如何調用c函數

直接嵌入c源代碼到go代碼里面

package main

/*

#include stdio.h

void myhello(int i) {

printf("Hello C: %d\n", i);

}

*/

import "C"

import "fmt"

func main() {

C.myhello(C.int(12))

fmt.Println("Hello Go");

}

需要注意的是C代碼必須放在注釋里面

import "C"語句和前面的C代碼之間不能有空行

運行結果

$ go build main.go ./main

Hello C: 12

Hello Go

分開c代碼到單獨文件

嵌在一起代碼結構不是很好看,很多人包括我,還是喜歡把兩個分開,放在不同的文件里面,顯得干凈,go源文件里面是go的源代碼,c源文件里面是c的源代碼。

$ ls

hello.c hello.h main.go

$ cat hello.h

void hello(int);

$ cat hello.c

#include stdio.h

void hello(int i) {

printf("Hello C: %d\n", i);

}

$ cat main.go

package main

// #include "hello.h"

import "C"

import "fmt"

func main() {

C.hello(C.int(12))

fmt.Println("Hello Go");

}

編譯運行

$ go build ./main

Hello C: 12

Hello Go

編譯成庫文件

如果c文件比較多,最好還是能夠編譯成一個獨立的庫文件,然后go來調用庫。

$ find mylib main

mylib

mylib/hello.h

mylib/hello.c

main

main/main.go

編譯庫文件

$ cd mylib

# gcc -fPIC -shared -o libhello.so hello.c

編譯go程序

$ cd main

$ cat main.go

package main

// #cgo CFLAGS: -I../mylib

// #cgo LDFLAGS: -L../mylib -lhello

// #include "hello.h"

import "C"

import "fmt"

func main() {

C.hello(C.int(12))

fmt.Println("Hello Go");

}

$ go build main.go

運行

$ export LD_LIBRARY_PATH=../mylib

$ ./main

Hello C: 12

Hello Go

在我們的例子中,庫文件是編譯成動態庫的,main程序鏈接的時候也是采用的動態庫

$ ldd main

linux-vdso.so.1 = (0x00007fffc7968000)

libhello.so = ../mylib/libhello.so (0x00007f513684c000)

libpthread.so.0 = /lib64/libpthread.so.0 (0x00007f5136614000)

libc.so.6 = /lib64/libc.so.6 (0x00007f5136253000)

/lib64/ld-linux-x86-64.so.2 (0x000055d819227000)

理論上講也是可以編譯成整個一靜態鏈接的可執行程序,由于我的機器上缺少靜態鏈接的系統庫,比如libc.a,所以只能編譯成動態鏈接。

GO語言學習系列八——GO函數(func)的聲明與使用

GO是編譯性語言,所以函數的順序是無關緊要的,為了方便閱讀,建議入口函數 main 寫在最前面,其余函數按照功能需要進行排列

GO的函數 不支持嵌套,重載和默認參數

GO的函數 支持 無需聲明變量,可變長度,多返回值,匿名,閉包等

GO的函數用 func 來聲明,且左大括號 { 不能另起一行

一個簡單的示例:

輸出為:

參數:可以傳0個或多個值來供自己用

返回:通過用 return 來進行返回

輸出為:

上面就是一個典型的多參數傳遞與多返回值

對例子的說明:

按值傳遞:是對某個變量進行復制,不能更改原變量的值

引用傳遞:相當于按指針傳遞,可以同時改變原來的值,并且消耗的內存會更少,只有4或8個字節的消耗

在上例中,返回值 (d int, e int, f int) { 是進行了命名,如果不想命名可以寫成 (int,int,int){ ,返回的結果都是一樣的,但要注意:

當返回了多個值,我們某些變量不想要,或實際用不到,我們可以使用 _ 來補位,例如上例的返回我們可以寫成 d,_,f := test(a,b,c) ,我們不想要中間的返回值,可以以這種形式來舍棄掉

在參數后面以 變量 ... type 這種形式的,我們就要以判斷出這是一個可變長度的參數

輸出為:

在上例中, strs ...string 中, strs 的實際值是b,c,d,e,這就是一個最簡單的傳遞可變長度的參數的例子,更多一些演變的形式,都非常類似

在GO中 defer 關鍵字非常重要,相當于面相對像中的析構函數,也就是在某個函數執行完成后,GO會自動這個;

如果在多層循環中函數里,都定義了 defer ,那么它的執行順序是先進后出;

當某個函數出現嚴重錯誤時, defer 也會被調用

輸出為

這是一個最簡單的測試了,當然還有更復雜的調用,比如調試程序時,判斷是哪個函數出了問題,完全可以根據 defer 打印出來的內容來進行判斷,非??焖?,這種留給你們去實現

一個函數在函數體內自己調用自己我們稱之為遞歸函數,在做遞歸調用時,經常會將內存給占滿,這是非常要注意的,常用的比如,快速排序就是用的遞歸調用

本篇重點介紹了GO函數(func)的聲明與使用,下一篇將介紹GO的結構 struct

新聞名稱:go語言執行代碼的函數 go執行js代碼
本文鏈接:http://vcdvsql.cn/article18/ddoipgp.html

成都網站建設公司_創新互聯,為您提供外貿建站、App開發、網站建設、域名注冊Google、網站策劃

廣告

聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯

網站托管運營