4. 總結
基本資料型別和陣列作為引數會進行值傳遞
接下來看乙個最簡單的例子
import
"fmt"
func
test
(num int
)func
main()
如果大家有其他語言的開發經驗,應該很容易看出來程式的輸出結果是
test :
11main :
10
我們再來看看引用傳遞是什麼結果
還是與上面的例子相同,只不過函式引數改為指標型別
import
"fmt"
func
test
(ptr *
int)
func
main()
我們再來看一下輸出結果
test :
11main :
11
這兩種不同的輸出結果,底層到底是如何實現的呢,
對於程式而言,在執行是作業系統會為其分配一塊記憶體,以滿足程式的執行需要,程式的程序會將這塊記憶體分為三個部分,分別是:1. 棧區 2. 堆區 3. **區。這是人為的邏輯上的劃分。
後面會有專門的文章來做golang的gc分析以及涉及到的逃逸分析等
下面我們就來對照一下**與邏輯上的分割槽來看一下到底是什麼輸出結果
首先,**從main函式開始執行,會在棧中開闢一塊區域用來儲存main函式的相關變數,注意這裡只是人為的邏輯分割槽。此時就在main函式的棧區中開闢出一塊空間用來儲存變數num
。
test
函式處,此時在棧中開闢一塊空間作為test函式的棧區,其中也會開闢一塊空間儲存乙個num
變數,只不過此時的test
函式棧區中的num
與main
函式棧區中的num
是兩個變數,其中test
函式棧去中的num
的值為main
函式棧區中num
值的拷貝。
此時程式執行到test
函式中,將test
函式棧區中num
做+1
操作,操作結束之後執行輸出語句,輸出的是test
函式棧區中的num
,故輸出test : 11
,之後程式返回到main
函式中繼續執行。
注意此時test
函式已經執行完畢,所以將test
函式的棧去已經自動從棧區中刪除了,此時再執行輸出語句,輸出的是main
函式棧區中儲存的num
,故輸出num : 10
。
與前面類似,也首先在棧去中開闢一塊空間儲存main
函式的相關變數。
程式向下執行,此時會在堆區中分配一塊空間,用來存放main
函式的一些引用變數,其中的ptr
為int
型別的指標,其值為main
函式中num
的位址,也就是ptr
為指向num
的指標。
函式執行到這裡的時候,會在棧區和堆區也分別建立test
函式的空間,其中在test
函式堆中儲存了乙個ptr
指標,其值為main
函式堆中ptr
值的拷貝,所以這兩個ptr
指標儲存的都是main
函式中num
的位址,也就是說test
函式堆區中的ptr
指標也指向main
函式棧區的num
變數。
此時操作test
堆區中的ptr
指標,也就像相當於操作main
函式中的num
變數,將其執行+1
操作,程式繼續執行故輸出為test : 11
。
程式繼續執行到main
函式中的輸出語句,此時已將test
棧區所佔空間自動釋放,test
堆區由gc
機制決定何時釋放。main
函式輸出的值就是main : 11
。
以上就是值傳遞與引用傳遞的分析。注意其中的棧,堆等均為人為的邏輯分割槽,每個程式在執行過程中也未必會嚴格按照此進行記憶體的分配,這裡是為了解釋方便,後期在做gc
等分析的時候也會有更詳細的說明。
Golang反射呼叫函式
首先,來看看這段 php view source print?1functionfoobar 4 funcs array 5 foobar foobar 6 hello foobar 7 8 funcs foobar 9 funcs hello 它會輸出 view source print?1mik...
C 函式呼叫機制
區域性變數占用的記憶體是在程式執行過程中 動態 地建立和釋放的。這種 動態 是通過棧由系統自動管理進行的。當任何乙個函式呼叫發生時,系統都要作以下工作 1 建立棧空間 3 為被調函式中的區域性變數分配空間,完成引數傳遞 4 執行被調函式函式體 5 釋放被調函式中區域性變數占用的棧空間 7 繼續主調函...
函式呼叫和傳值呼叫
在使用函式時,所有的實參都是通過 傳值 方式傳遞的。這意味著每個實參都被求值,求值結果代替對應的形式引數,並且在函式中作為區域性變數使用。如果乙個變數傳遞給乙個函式,這個變數在呼叫環境中所儲存的值並不會被函式所修改。include int compute sum int n int main voi...