Solidity 中的函數(shù)
1、solidity 函數(shù)定義
function 函數(shù)名(參數(shù)列表) 修飾符 returns (返回類型){}
function eatHamburgers(string _name, uint _amount) {
// 這是一個(gè)名為 eatHamburgers 的函數(shù)榜跌,它接受兩個(gè)參數(shù):一個(gè) string類型的 和 一個(gè) uint類型的〔戮荆現(xiàn)在函數(shù)內(nèi)部還是空的
// 習(xí)慣上函數(shù)里的變量都是以 _ 開頭 (但不是硬性規(guī)定) 以區(qū)別全局變量。
}
2、solidity 函數(shù)的可見性定義符(4個(gè))
Solidity 定義的函數(shù)的屬性默認(rèn)為公共(public)坝冕。 這就意味著任何一方 (或其它合約) 都可以調(diào)用你合約里的函數(shù)。
pragma solidity ^0.4.14;
contract HelloWorld{
function getNum(uint num) {
}
// 此函數(shù)等價(jià)于
function getNum(uint num) public {
}
}
顯然瓦呼,不是什么時(shí)候都需要這樣喂窟,而且這樣的合約易于受到攻擊。 所以將自己的函數(shù)定義為私有是一個(gè)好的編程習(xí)慣央串,只有當(dāng)你需要外部世界調(diào)用它時(shí)才將它設(shè)置為公共磨澡。
如何定義一個(gè)私有的函數(shù)呢?
uint[] numbers;
function _addToArray(uint _number) private {
numbers.push(_number);
}
//這意味著只有我們合約中的其它函數(shù)才能夠調(diào)用這個(gè)函數(shù),給 numbers 數(shù)組添加新成員质和。
可以看到稳摄,在函數(shù)名字后面使用關(guān)鍵字 private 即可。和函數(shù)的參數(shù)類似饲宿,私有函數(shù)的名字用(_)起始厦酬。
函數(shù)的可見性定義符還有internal 和 external
- public:在外部和內(nèi)部均可見(創(chuàng)建存儲(chǔ)/狀態(tài)變量的訪問者函數(shù))
- private:僅在當(dāng)前合約中可見
- external: 只有外部可見(僅對(duì)函數(shù))- 僅僅在消息調(diào)用中(通過this.fun)
- internal: 只有內(nèi)部可見
3、solidity 函數(shù)的返回值
要想函數(shù)返回一個(gè)數(shù)值瘫想,按如下定義:
string greeting = "What's up dog";
function sayHello() public returns (string) {
return greeting;
}
Solidity 里仗阅,函數(shù)的定義里可包含返回值的數(shù)據(jù)類型(如本例中 string)。
-----------------------------------------------------------
// 第二種返回寫法
string greeting = "What's up dog";
function sayHello() public returns (string aa) {
aa = greeting;
}
// 不寫return 關(guān)鍵字那么就得在返回列表中制定返回名
4国夜、solidity 函數(shù)的修飾符(3個(gè))
- view 修飾符
上面的函數(shù)實(shí)際上沒有改變 Solidity 里的狀態(tài)减噪,即,它沒有改變?nèi)魏沃祷蛘邔懭魏螙|西车吹。這種情況下我們可以把函數(shù)定義為 view, 意味著它只能讀取數(shù)據(jù)不能更改數(shù)據(jù)筹裕,老版本為 constant ,但是現(xiàn)在不能寫了:
function sayHello() public view returns (string) { }
因此用 view 標(biāo)記一個(gè)函數(shù)窄驹,意味著告訴 web3.js饶碘,運(yùn)行這個(gè)函數(shù)只需要查詢你的本地以太坊節(jié)點(diǎn),而不需要在區(qū)塊鏈上創(chuàng)建一個(gè)事務(wù)(事務(wù)需要運(yùn)行在每個(gè)節(jié)點(diǎn)上馒吴,因此花費(fèi) gas)扎运。
- pure 修飾符
Solidity 還支持 pure 函數(shù), 表明這個(gè)函數(shù)甚至都不訪問應(yīng)用里的數(shù)據(jù)瑟曲,
function _multiply(uint a, uint b) private pure returns (uint) {
return a * b;
}
這個(gè)函數(shù)甚至都不讀取應(yīng)用里的狀態(tài) — 它的返回值完全取決于它的輸入?yún)?shù),在這種情況下我們把函數(shù)定義為 pure.
可能很難記住何時(shí)把函數(shù)標(biāo)記為 pure/view豪治。 幸運(yùn)的是洞拨, Solidity 編輯器會(huì)給出提示,提醒你使用這些修飾符负拟。這兩種在被從合約外部調(diào)用的時(shí)候都不花費(fèi)任何gas
- payable 修飾符 --- 可支付
允許函數(shù)在調(diào)用同時(shí)接收Ether烦衣,payable 修飾符是讓 Solidity 和以太坊變得如此酷的一部分 —— 它們是一種可以接收以太的特殊函數(shù)。
當(dāng)你在調(diào)用一個(gè)普通網(wǎng)站服務(wù)器上的API函數(shù)的時(shí)候掩浙,你無法用你的函數(shù)傳送美元——你也不能傳送比特幣
但是在以太坊中花吟, 因?yàn)殄X (以太), 數(shù)據(jù) (事務(wù)負(fù)載), 以及合約代碼本身都存在于以太坊厨姚。你可以在同時(shí)調(diào)用函數(shù) 并付錢給另外一個(gè)合約衅澈。
這就允許出現(xiàn)很多有趣的邏輯, 比如向一個(gè)合約要求支付一定的錢來運(yùn)行一個(gè)函數(shù)
contract OnlineStore {
function buySomething() external payable {
// 檢查以確定0.001以太發(fā)送出去來運(yùn)行函數(shù):
// msg.value 是一種可以查看向合約發(fā)送了多少以太的方法谬墙,另外 ether 是一個(gè)內(nèi)建單位今布。
require(msg.value == 0.001 ether);
// 如果為真,一些用來向函數(shù)調(diào)用者發(fā)送數(shù)字內(nèi)容的邏輯
transferThing(msg.sender);
}
}
如果一個(gè)函數(shù)沒標(biāo)記為payable拭抬, 而你嘗試?yán)蒙厦娴姆椒òl(fā)送以太部默,函數(shù)將拒絕你的事務(wù)。
5造虎、solidity 函數(shù)的自定義修飾符
我們先來寫個(gè)onlyOwner自定義的函數(shù)修飾符
/**
* @dev 調(diào)用者不是‘主人’傅蹂,就會(huì)拋出異常
*/
pragma solidity ^0.4.14;
contract Ownable {
address public owner;
// 構(gòu)造函數(shù),當(dāng)合約部署的時(shí)候就會(huì)自動(dòng)執(zhí)行這個(gè)函數(shù)算凿,并且只執(zhí)行一次
function Ownable() public {
owner = msg.sender;
}
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
//注意份蝴! `onlyOwner`上場(chǎng) :
function hello() public onlyOwner returns(bool){
return ture;
}
}
注意 hello 函數(shù)上的 onlyOwner 修飾符。 當(dāng)你調(diào)用 hello 時(shí)澎媒,首先執(zhí)行 onlyOwner 中的代碼, 執(zhí)行到 onlyOwner 中的 _; 語句時(shí)波桩,程序再返回并執(zhí)行 hello 中的代碼戒努。
我們?cè)賹憘€(gè)onlyOwner可以傳參的自定義的函數(shù)修飾符
/**
* @dev 調(diào)用者不是‘主人’,就會(huì)拋出異常
*/
pragma solidity ^0.4.14;
contract Ownable {
address public owner;
// 構(gòu)造函數(shù)镐躲,當(dāng)合約部署的時(shí)候就會(huì)自動(dòng)執(zhí)行這個(gè)函數(shù)储玫,并且只執(zhí)行一次
function Ownable() public {
owner = msg.sender;
}
modifier onlyOwner(uint i) {
require(msg.value== i);
_;
}
// 注意! `onlyOwner`上場(chǎng) :
function hello(uint i) public onlyOwner(i) returns(bool){
return ture;
}
}
當(dāng)我們調(diào)用hello 的時(shí)候需要傳遞 參數(shù) i 進(jìn)去, 傳進(jìn)去后先調(diào)用 修飾符 onlyOwner函數(shù)萤皂,若require()內(nèi)的結(jié)果不是true撒穷,則拋出異常,為true 才會(huì)繼續(xù)執(zhí)行下去
目前我們可以給函數(shù)添加多種修飾符了裆熙,這些修飾符可以同時(shí)作用于一個(gè)函數(shù)定義上:
function test() external view onlyOwner anotherModifier { /* ... */ }