本教程使用的開發環境是一款在線編譯器——ChainIDE,具體的使用方法在之前的文章當中已經有講解過,有需要的同學可以自行查看。
序言
本章講的是關於映射以及類型轉換的兩部分內容。其中,映射是一種能讓我們通過“名字”就找到對應的人的數據結構,而類型轉換則是在不同的數據類型之間的變換,以達到對應表達式所需的數據類型。
映射
mapping(_KeyType => _KeyValue)
簡單來說,映射就是一個哈希表,每一個key與一個value互相對應,通過知道鍵值可以快速地定位到value。
不同於哈希表的是,key值的範圍可以更廣,可以是除了映射本身、邊長數組、合約、枚舉、結構體以外的所有類型,而value值則是所有類型都可以。
映射的應用場景非常廣泛,在這裏我舉一個例子讓大家能更好的理解這個數據結構。
權限管理系統
在區塊鏈當中,不同的地址發出某個請求的時候合約往往需要辨識它是否擁有請求的權利。在這裏我們就可以通過一個地址-權利(bool)的映射來調用這個地址對應的權利,判斷是否完成請求。
我會寫一個示例合約來講解如何使用一個映射管理權限和設置權限。
pragma solidity >=0.4.22 <0.6.0;
contract Authentication
{
mapping(address=>bool) Auth_list;
function set_allow(address allow_address) public {
Auth_list[allow_address] = true;
}
function set_deny(address deny_address) public {
Auth_list[deny_address] = false;
}
function query_auth(address target_address) public view returns(bool){
if(Auth_list[target_address]==true)
{
return true;
}
else
{
return false;
}
}
}
首先我們創建一個映射變量Auth_list,用於儲存地址以及它對應的權限,權限的代表爲true和false。
接着我們通過兩個函數來對地址的權限進行設置,分別是set_allow和set_deny,輸入的參數爲對應的地址,在執行了這個函數之後就會將這個地址的權限保存到這個合約的Auth_list當中。
這裏有幾點需要注意:1.調用這兩個函數都需要花費gas,因爲更改了存儲在區塊鏈上的內存。2.這個函數的權限可以通過modifier設置,指定爲特定的人或者白名單,這個後面會講到。
最後,我們可以通過query_auth來查詢這個合約當中不同地址的訪問權限,獲得一個公開透明可查詢的結果。
類型轉換
類型轉換在Solidity當中屬於一個比較常見的部分,當兩個類型不同的變量在運算符的兩側時,就會涉及到類型轉換,這種類型轉換又分爲隱式轉換(自動轉換)和顯式轉換(人工轉換)。
隱式轉換
通俗來說,這種隱式轉換就是在程序員不知道的情況下,編譯器自動對這個類型進行向下兼容的一個過程,比如說uint8可以被uint16兼容,因爲16是大於8的,內存可以包含uint8的內容。任何可以轉換成 uint160 的類型都可以轉換成 address 類型。
但是int8就不可以轉換成uint256,因爲int8包含了負數,它並不屬於無符號數的子集。
顯式轉換
顯示轉換就是在隱式轉換無法生效的情況下,人爲進行的轉換,但是人爲進行的轉換就必然會導致一些問題,比如說位數的截斷,以及無法覆蓋導致的溢出等等。
接下來我通過幾個實際執行的例子讓大家看一下不同類型顯示轉換的結果。
int轉uint
function int_uint() public pure returns (uint16)
{
int8 a = -1;
uint16 b = uint16(a);
return (b); //返回值爲65535
}
這裏可以看到我想把-1轉成uint,轉換是成功了,但是返回的值出現了錯誤,這是由於在計算機儲存當中,-1的補碼對應的值就是65535。
多位uint轉少位uint
function biguint_smalluint() public pure returns(uint8)
{
uint16 a = 12515;
uint8 b = uint8(a);
return b; //返回值爲227
}
在這裏的返回值可能會有些奇怪,大家看不出來是爲什麼,其實這是在轉換爲少位數的uint後只留下低位的結果。
我們把這兩個數字都轉換成16進制,12515對應的是30e3,227對應的是e3,這樣就可以很明顯的看到只取了後面兩個字節的數值。
在條件允許的情況下,最好不要進行顯式轉換,因爲顯式轉換有可能會因爲輸入變量的不同導致意想不到的bug,在合約部署之後是一個很大的隱患。
參考資料
https://solidity.tryblockchain.org/Solidity-mapping-%E6%98%A0%E5%B0%84.html
https://solidity-cn.readthedocs.io/zh/develop/types.html#index-22