در این آموزش با مفهوم ساختارها (Structs) در سالیدیتی آشنا میشوید و یاد میگیرید چطور با استفاده از آنها داده های مرتبط را بهصورت منظم در قراردادهای هوشمند ذخیره و مدیریت کنید.
ساختارها در سالیدیتی چیست؟
در سالیدیتی، ساختارها (Structs) ابزاری برای گروه بندی متغیرهای مرتبط در قالب یک نوع داده ترکیبی هستند. با استفاده از ساختارها میتوان داده هایی از انواع مختلف مانند عدد، رشته، آدرس و… را در کنار یکدیگر قرار داد و آنها را به صورت منظم و قابل مدیریت نگه داشت. این قابلیت به ویژه زمانی کاربرد دارد که نیاز به ذخیره اطلاعات پیچیده تری مانند مشخصات کاربران، سفارش ها یا داده های تراکنش باشد.
استفاده از ساختارها نه تنها کد شما را خواناتر میکند، بلکه باعث کاهش تکرار و افزایش بهره وری در توسعه قراردادهای هوشمند نیز میشود. برای مثال، به جای نگهداری نام و موجودی کاربر در دو mapping جداگانه، میتوان هر دو را در یک struct قرار داد و آن struct را با آدرس کاربر در یک mapping ذخیره کرد. ساختارها همچنین میتوانند در آرایه ها و mapping ها استفاده شوند و به شکل مؤثری داده ها را دسته بندی کنند.
آموزش ساختارها در سالیدیتی
ساختارها در سالیدیتی عملکردی مشابه زبان C دارند. همانطور که گفتیم آن ها چندین متغیر را در یک نوع داده مرکب گروهبندی میکنند که میتواند برای سازماندهی داده ها و ایجاد ساختارهای داده ای پیچیده تر بسیار مفید باشد.
در اینجا نحوه تعریف یک ساختار در Solidity آمده است:
1 2 3 4 5 6 7 8 9 |
contract StructsExample { struct Foo { uint256 a; uint256 b; } Foo public myFoo; } |
myFoo
یک متغیر عمومی از نوع ساختار Foo
است که هر دو مقدار uint256 a
و uint256 b
را ذخیره میکند. همانطور که میبینید، اگر آن را در Remix مستقر کنیم، myFoo
چنین مقداری را بازمیگرداند:
برای ارسال یک ساختار در Remix به تابعی که یک ساختار را به عنوان آرگومان میپذیرد (که در ادامه بیشتر درباره آن صحبت خواهیم کرد)، آن را به شکل زیر رمزگذاری (encode) کنید:
تابعی که در این مثال مطرح شده، ساختار Foo
بالا را میگیرد که شامل دو متغیر uint256
است. ممکن است فرمت کردن آن مانند یک آرایه کمی گیجکننده به نظر برسد، اما روش کار همین است.
برای ایجاد یک نمونه جدید از Foo
در Solidity، بهسادگی مقادیر را در ساختار Foo
قرار دهید:
- Foo(a,b)
برای دسترسی یا اختصاص مقدار به هر متغیر مجزا در ساختار myFoo
، از نگارش نقطهای استفاده کنید:
- myFoo.a
- myFoo.b
چرا از ساختارها در سالیدیتی استفاده میکنیم؟
فرض کنید یک قرارداد سپرده داریم که نام سپرده گذار و موجودی او را ذخیره میکند. Struct ها در چنین مواردی ساختاردهی کد را سادهتر و قابلفهمتر میکنند.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
contract DepositOnly { mapping(address => string) public name; mapping(address => uint256) public balance; function deposit( string memory _name ) external payable { balance[msg.sender] += msg.value; name[msg.sender] = _name; } } |
در قرارداد بالا، نام و موجودی سپرده گذار در دو ساختار داده ای mapping جداگانه ذخیره میشوند.
متغیر آدرس در هر دو mapping برای نام و موجودی msg.sender
تکرار شده است، و به همین دلیل کارایی مناسبی ندارد.
اینجاست که ساختارها (structs) به کار میآیند. ما میتوانیم هر دو مقدار نام و موجودی را در یک متغیر struct ثبت کرده و آن را فقط در یک mapping کلید-مقدار ذخیره کنیم، به این شکل:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
contract DepositOnly { struct Person { string name; uint256 balance; } mapping(address => Person) public depositor; function deposit( string memory _name ) external payable { depositor[msg.sender] = Person(_name, msg.value); } } |
میبینید چقدر مفید است؟ این کار باعث تمیزتر و بهینه تر شدن کد شما میشود.
چگونه از ساختارها در سالیدیتی استفاده کنیم؟
ساده است، در ادامه یک مثال آورده شده است:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
contract StructsExample { struct Foo { uint256 a; uint256 b; } Foo public myFoo; function assignMyFoo( uint256 _a, uint256 _b ) public { myFoo = Foo(_a, _b); } function assignA( uint256 _a ) public { myFoo.a = _a; } function accessA() public view returns(uint256) { return myFoo.a; } } |
اگر بخواهید struct Foo
را به عنوان آرگومان به تابعی پاس بدهید یا از آن به عنوان مقدار برگشتی استفاده کنید، باید چند قانون را رعایت کنید:
-
ساختارهایی که به عنوان آرگومان ارسال میشوند باید به صورت
memory
تعریف شوند. -
ساختارهایی که به عنوان خروجی تابع برمیگردند نیز باید به صورت
memory
تعریف شوند. به این صورت:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
contract StructsExample { struct Foo { uint256 a; uint256 b; } Foo myFoo; function passStructAsArgument( Foo memory foo ) public { myFoo = foo; } function returnAStruct() public view returns (Foo memory) { return myFoo; } } |
1 2 3 |
struct Foo { Foo innerFoo; // disallowed } |
آرایه ها و Mapping ها در سالیدیتی
ساختارها در سالیدیتی را میتوان به عنوان نوع مقدار در آرایه ها و Mapping ها استفاده کرد. برای مثال، میتوانید یک آرایه داینامیک از نمونه های Foo
به این صورت ایجاد کنید:
1 2 3 4 5 6 7 8 9 10 |
contract StructsExample { struct Foo { uint256 a; uint256 b; } Foo[] public arrayFoo; } |
arrayFoo
یک آرایه از نمونههای Foo
است:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
contract StructsExample { struct Foo { uint256 a; uint256 b; } Foo[] public arrayFoo; function addFooToArray( uint256 _a, uint256 _b ) public { arrayFoo.push(Foo(_a, _b)); } function readFooFromArray( uint256 _index ) public view returns(Foo memory){ return arrayFoo[_index]; } function readFooA( uint256 _index ) public view returns(uint256){ return arrayFoo[_index].a; } function modifyFooA( uint256 _index, uint256 _a ) public { arrayFoo[_index].a = _a; } function setFooAtIndex( uint256 _index, uint256 _a, uint256 _b ) public { arrayFoo[_index] = Foo(_a, _b); } } |
Foo
باشند:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
contract StructsExample { struct Foo { uint256 a; uint256 b; } mapping(address => Foo) public mappingFoo; function insertFoo( uint256 _a, uint256 _b ) public { mappingFoo[msg.sender] = Foo(_a, _b); } } |
تا اینجا باید واضح باشد که چه اتفاقی در حال افتادن است. ما یک mapping از address ⇒ struct Foo
داریم به نام mappingFoo
.
برای اختصاص دادن یک نمونه از Foo
به یک mapping آدرسی، به این صورت عمل میکنیم:
1 2 3 4 5 6 7 |
function insertFoo( uint256 _a, uint256 _b ) public { mappingFoo[msg.sender] = Foo(_a, _b); } |
1 2 3 |
function modifyFoo(uint256 _a) public { mappingFoo[msg.sender].a = _a; } |
مثال دنیای واقعی
یک کاربرد عملیتر میتواند در یک سیستم بلیت باشد. ما یک قرارداد BuyTickets
داریم که هر بلیت را با قیمت ۰.۰۱ اتر میفروشد. هر آدرس نمیتواند بیشتر از ۱۰ بلیت خریداری کند و ما تابعی داریم که اطلاعات بلیت های یک آدرس را نمایش میدهد.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
contract BuyTickets { uint256 public constant TICKET_PRICE = 0.01 ether; struct Ticket { string name; uint256 numberOfTickets; } mapping(address => Ticket) public tickets; function buyTicket( string memory _name, uint256 _numberOfTickets ) external payable { require(msg.value == _numberOfTickets * TICKET_PRICE, "Wrong Value"); require(_numberOfTickets <= 10, "Maximum Limit Exceeded"); require(tickets[msg.sender].numberOfTickets + _numberOfTickets <= 10, "Maximum Limit Reached"); tickets[msg.sender].name = _name; tickets[msg.sender].numberOfTickets += _numberOfTickets; } function displayTicket( address _ticketHolder ) external view returns (Ticket memory) { return(tickets[_ticketHolder]); } } |
راستی! برای دریافت مطالب جدید در کانال تلگرام یا پیج اینستاگرام سورس باران عضو شوید.
- انتشار: ۱۹ اردیبهشت ۱۴۰۴
دسته بندی موضوعات
- آموزش ارز دیجیتال
- آموزش برنامه نویسی
- آموزش متنی برنامه نویسی
- اطلاعیه و سایر مطالب
- پروژه برنامه نویسی
- دوره های تخصصی برنامه نویسی
- رپورتاژ
- فیلم های آموزشی
- ++C
- ADO.NET
- Adobe Flash
- Ajax
- AngularJS
- apache
- ARM
- Asp.Net
- ASP.NET MVC
- AVR
- Bootstrap
- CCNA
- CCNP
- CMD
- CSS
- Dreameaver
- EntityFramework
- HTML
- IOS
- jquery
- Linq
- Mysql
- Oracle
- PHP
- PHPMyAdmin
- Rational Rose
- silver light
- SQL Server
- Stimulsoft Reports
- Telerik
- UML
- VB.NET&VB6
- WPF
- Xml
- آموزش های پروژه محور
- اتوکد
- الگوریتم تقریبی
- امنیت
- اندروید
- اندروید استودیو
- بک ترک
- بیسیک فور اندروید
- پایتون
- جاوا
- جاوا اسکریپت
- جوملا
- دلفی
- دوره آموزش Go
- دوره های رایگان پیشنهادی
- زامارین
- سئو
- ساخت CMS
- سی شارپ
- شبکه و مجازی سازی
- طراحی الگوریتم
- طراحی بازی
- طراحی وب
- فتوشاپ
- فریم ورک codeigniter
- فلاتر
- کانستراکت
- کریستال ریپورت
- لاراول
- معماری کامپیوتر
- مهندسی اینترنت
- هوش مصنوعی
- یونیتی
- کتاب های آموزشی
- Android
- ASP.NET
- AVR
- LINQ
- php
- Workflow
- اچ تی ام ال
- بانک اطلاعاتی
- برنامه نویسی سوکت
- برنامه نویسی موبایل
- پاسکال
- پایان نامه
- پایتون
- جاوا
- جاوا اسکریپت
- جی کوئری
- داده کاوی
- دلفی
- رباتیک
- سئو
- سایر کتاب ها
- سخت افزار
- سی اس اس
- سی پلاس پلاس
- سی شارپ
- طراحی الگوریتم
- فتوشاپ
- مقاله
- مهندسی نرم افزار
- هک و امنیت
- هوش مصنوعی
- ویژوال بیسیک
- نرم افزار و ابزار برنامه نویسی
- وردپرس