原文標題:《Solidity 極簡入門:3. 函數類型》

作者:0xAA

我最近在重新學solidity,鞏固一下細節,也寫一個「Solidity 極簡入門」,供小白們使用(編程大佬可以另找教程),每週更新1-3 講。

所有代碼開源在github:github.com/AmazingAng/WTFSolidity

Solidity 中的函數

solidity 官方文檔裡把函數歸到數值類型,但我覺得差別很大,所以單獨分一類。我們先看一下solidity 中函數的形式:

Solidity極簡入門 | 第三講:函數類型

看著些複雜,咱們從前往後一個一個看(方括號中的是可寫可不寫的關鍵字):

1. function:聲明函數時的固定用法,想寫函數,就要以function 關鍵字開頭。

2. ():圓括號裡寫函數的參數,也就是要輸入到函數的變量類型和名字。

3. {internal|external|public|private} :函數可見性說明符,一共4 種。沒標明函數類型的,默認internal。

- public: 內部外部均可見,並且自動給stoage 變量生成getter 函數 。

- private: 只能從本合約內部訪問,繼承的合約也不能用。

- external: 只能從合約外部訪問(但是可以用this.f() 來調用,f 是函數名)

- internal: 只能從合約內部訪問,繼承的合約可以用。

4. [pure|view|payable]:決定函數權限/功能的關鍵字。 payable 很好理解,帶著它的函數,運行的時候可以給合約轉入ETH。 pure 和view 的介紹見下一節。

5. [returns ()]:函數返回的變量類型和名稱。

到底什麼是Pure 和View?

我剛開始學solidity 的時候,一直不理解pure 跟view 關鍵字,因為別的語言沒有類似的關鍵字。 solidity 加入這兩個關鍵字,我認為是因為gas fee。合約的狀態變量存儲在鏈上,gas fee 很貴,如果不改寫這些變量,就不用付gas。調用pure 跟view 的函數是不需要付gas 的。

我畫了一個馬里奧插畫,幫助大家理解。在插畫裡,我把合約中的狀態變量(存儲在鏈上)比作碧池公主,三種不同的角色代表不同的關鍵字。

Solidity極簡入門 | 第三講:函數類型

WTH is pure and view in solidity?

pure,中文意思是「純」,在solidity 裡理解為「純純牛馬」。包含pure 關鍵字的函數,不能讀取也不能寫入存儲在鏈上的狀態變量。就像小怪一樣,看不到也摸不到碧池公主。

view,「看」,在solidity 裡理解為「看客」。包含view 關鍵字的函數,能讀取但也不能寫入狀態變量。類似馬里奧,能看到碧池,但終究是看客,不能入洞房。

不寫pure 也不寫view,函數既可以讀取也可以寫入狀態變量。類似馬里奧里的boss,可以對碧池公主為所欲為。

代碼

1. pure vs view

我們在合約裡定義一個狀態變量_number = 5。

Solidity極簡入門 | 第三講:函數類型

定義一個add() function,每次調用,輸出_number + 1。

Solidity極簡入門 | 第三講:函數類型

如果add() 包含了pure 關鍵字,例如function add() pure external,就會報錯。因為pure(純純牛馬)是不配讀取合約裡的狀態變量的,更不配改寫。那pure 函數能做些什麼?舉個例子,你可以給函數傳遞一個參數_number,然後讓他返回_number+1。

Solidity極簡入門 | 第三講:函數類型

如果add() 包含view,比如function add() view external,也會報錯。因為view 能讀取,但不能夠改寫狀態變量。可以稍微改寫下方程,讓他不改寫_number,而是返回一個新的變量。

Solidity極簡入門 | 第三講:函數類型

2. Internal vs External

Solidity極簡入門 | 第三講:函數類型

我們定義一個internal 的minus() 函數,每次調用使得number 變量減1。由於是internal,只能由合約內部調用。我們再定義一個external 的minusCall() 函數,調用minus()。這樣,人們就能通過調用minusCall() 來間接調用internal 的minus()。

3. Payable

Solidity極簡入門 | 第三講:函數類型

我們定義一個external payable 的minusPayable() 函數,間接的調用minus(),並且返回合約裡的ETH 餘額(this 關鍵字可以讓我們引用合約地址)。我們調用minusPayable() 時,往合約裡轉入1 個ETH。

Solidity極簡入門 | 第三講:函數類型

我們可以在返回的信息中看到,合約的餘額是1 ETH。

Solidity極簡入門 | 第三講:函數類型

總結

在第三講,我們介紹了solidity 中的函數類型,比較難理解的是pure 和view,在其他語言中沒出現過。 solidity 擁有pure 和view 兩種關鍵字主要是為了節省gas fee 和控制函數權限,這兩種方程都是不消耗gas 的。下一講我們會介紹引用和映射兩種類型,並介紹更複雜的函數。