Storage
、Memory
和Calldata
是用於定義變量存儲位置的關鍵字,它們各自有不同的適用情境和用法。
Storage
是用於存儲合約狀態變量的位置。這些變量存儲在區塊鏈上,並且在合約的生命週期內持續存在。Storage
變量的變化會影響合約的狀態,並且會持久化存儲在區塊鏈上。當你需要修改合約的狀態或者存儲長期存在的數據時,應該使用Storage
。
Memory
是用於存儲函數內部的臨時變量的位置。這些變量只在函數被調用時存在,並且在函數結束時被清除。Memory
變量可以被修改,並且可以用於函數參數和函數內部的變量。當你需要在函數內部處理暫時數據,並且不需要將數據持久化存儲在區塊鏈上時,應該使用Memory
。
Calldata
是用於存儲外部函數參數的位置。這些參數是不可修改的,並且只在函數被調用時存在。Calldata
變量不能被修改,並且在函數結束時不會被清除。當你需要在外部函數中處理不可修改的數據時,應該使用Calldata
。
學校通訊錄合約 - 包含添加學生資訊、查詢學生資訊和更新學生資訊的功能。
addStudent
函數使用calldata
來接收參數,因為這些參數是從外部呼叫函數時傳遞的,並且不需要修改。getStudent
函數使用storage
來存儲學生資訊,因為這些資訊需要永久存儲在區塊鏈上,並且可以被合約中的任何函數訪問和修改。updateStudent
函數使用memory
來臨時存儲新的學生資訊,因為這些資訊只在函數執行期間需要,並且不需要永久存儲在區塊鏈上。storage
允許學校管理員更新學生的聯繫方式, 且我們將使用storage
來存儲學生的資訊。updateStudentContact
,該函數允許學校管理員更新學生的聯繫方式。這個函數使用storage
來直接修改學生資訊,因為我們需要修改存儲在區塊鏈上的數據。這種方法避免了使用臨時變量(如memory
)來複製數據,從而節省了gas成本並提高了效率。// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract SchoolDirectory {
// 使用mapping來儲存學生資訊,鍵為學生ID,值為學生資訊
mapping(uint => Student) public students;
// 學生資訊結構
struct Student {
string name;
uint age;
string contact;
}
// 添加學生資訊的函數,使用calldata來接收參數
function addStudent(uint id, string calldata name, uint age, string calldata contact) external {
students[id] = Student(name, age, contact);
}
// 查詢學生資訊的函數,使用storage來存儲學生資訊
function getStudent(uint id) external view returns (string memory name, uint age, string memory contact) {
Student storage student = students[id];
return (student.name, student.age, student.contact);
}
// 更新學生資訊的函數,使用memory來臨時存儲資訊
function updateStudent(uint id, string calldata name, uint age, string calldata contact) external {
Student memory newStudent = Student(name, age, contact);
students[id] = newStudent;
}
// 更新學生聯繫方式的函數,使用storage來存儲學生資訊
function updateStudentContact(uint id, string calldata newContact) external {
// 使用storage關鍵字來直接修改學生資訊
students[id].contact = newContact;
}
}