概要
mappingの能力を最大限に引き出す、Solidityの「構造体 (struct)」を徹底解説します。ユーザーID・名前・残高といった複数の関連データを、あなただけのオリジナルなデータ型にまとめる方法を学習。
mapping(address => User)という王道パターンを使い、複雑な情報を整理整頓し、本格的なDAppのデータ層を設計するスキルが身につきます。
-

-
Solidity学習講座:最終版 目次(全20話)
基礎編 第1話:未来のインターネットへようこそ!Solidityとスマートコントラクトの全体像 第2話:準備は1分!ブラウザだけで開発できる「Remix IDE」の基本操作 第3話:記念すべき初コント ...
続きを見る
目次
はじめに
第7話で、あなたはmappingという魔法の杖を手に入れました。mapping(address => uint)という一行で、無数のユーザーの残高を管理できるようになったのです。これは大きな進歩でしたね。
しかし、すぐに新たな課題が見えてきます。もし、あなたがユーザー管理システムを作りたいとして、ユーザーごとに以下の情報を保存したい場合はどうすればよいでしょうか?
- ユーザーID(
uint) - ユーザー名(
string) - 会員ステータス(
bool) - ポイント残高(
uint)
もちろん、mapping(address => uint) userIds;、mapping(address => string) userNames;... というように、情報の種類ごとにマッピングを増やすことも可能です。しかし、このアプローチは煩雑で、管理が大変になり、コードの見通しも悪くなってしまいます。
この課題をエレガントに解決するのが、今回学ぶ**struct(構造体)**です。
structは、関連する複数のデータを一つのグループにまとめ、あなただけのオリジナルなデータ型を作成するための機能です。これをmappingと組み合わせることで、あなたのスマートコントラクトのデータ管理能力は飛躍的に向上し、プロフェッショナルな設計への扉が開かれます。
structとは? あなただけのデータ型を作る設計図
structとは、複数の異なるデータ型を持つ変数を一つに束ねた、ユーザー定義の複合データ型です。uintやstringがSolidityに組み込まれた基本データ型であるのに対し、structはあなたが自由に設計できるカスタムデータ型と言えます。
structの定義は非常にシンプルです。
Solidity
struct 構造体の名前 {
データ型1 変数名1;
データ型2 変数名2;
// ... 必要なだけ変数を定義
}
先ほどのユーザー情報の例で、Userという名前のstructを定義してみましょう。
Solidity
struct User {
uint id;
string name;
bool isMember;
uint pointBalance;
}
これで、uintやaddressなどと同じように、**User**という新しいデータ型が誕生しました。このUser型は、id, name, isMember, pointBalanceという4つの情報を常にワンセットで保持する、便利な「入れ物」として機能します。
structの真価:mappingとの組み合わせ
structの本当の力は、mappingと組み合わせたときに発揮されます。これこそが、Solidityにおけるデータ管理の王道パターンです。
mapping(address => User) public users;
この一行が持つ意味、想像できますか?
これは、「usersという名前のマッピングを定義します。これは、キーとしてaddressを受け取り、その値として、先ほど私たちが定義した**User構造体の全データ**を返します」ということです。
たった一つのmappingで、ユーザーごとのID、名前、会員ステータス、ポイント残高を、すべてまとめて管理できるようになったのです。すっきりと整理整頓され、非常にパワフルだと思いませんか?
structを実際に使ってみよう
それでは、ユーザーを登録し、その情報を更新するコントラクトを例に、structの具体的な使い方を学んでいきましょう。
1. structデータの作成と書き込み
mappingに新しいUserデータを追加するには、どうすればよいでしょうか? ユーザー登録を行う関数を作ってみましょう。
Solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract UserManagement {
// User構造体の定義
struct User {
uint id;
string name;
bool isMember;
}
// addressをキー、Userを値とするマッピング
mapping(address => User) public users;
uint nextUserId = 1; // ユーザーIDを自動採番するため
// ユーザーを登録する関数
function register(string memory _name) public {
// すでに登録済みでないことを確認
require(users[msg.sender].id == 0, "User already registered.");
// `users`マッピングに新しいUser構造体のデータを書き込む
users[msg.sender] = User(nextUserId, _name, true);
nextUserId++; // 次のユーザーのためにIDを1増やす
}
}
ここでregister関数に注目してください。string memory _nameという見慣れないキーワードが出てきましたね。stringやstructのような複雑なデータ型を関数の引数や関数内のローカル変数として使う場合、そのデータがどこに保存されるかを示す**「データロケーション」を指定する必要があります。memoryは、「そのデータは一時的なもので、関数実行中のみメモリ上に存在する」という意味です。今は「stringを引数に取るときはmemoryを付ける」**と覚えておけば大丈夫です。
users[msg.sender] = User(nextUserId, _name, true);の行が、structデータを作成してマッピングに保存している核心部分です。User(...)のように、struct定義と同じ順番で値を渡すことで、新しいUserデータが生成されます。
2. structデータの読み取りと更新
mappingに保存されたUserデータ。その中の特定の情報(例えば名前だけ)を読み取ったり、更新したりするにはどうすればよいでしょうか? ドット(.)を使ってアクセスします。
マッピング名[キー].構造体の変数名
この記法で、個別のデータにピンポイントでアクセスできます。例えば、登録した自分の名前を後から変更する関数を書いてみましょう。
Solidity
// ユーザー名を更新する関数
function updateName(string memory _newName) public {
// ユーザーが登録済みであることを確認
require(users[msg.sender].id != 0, "User not registered.");
// usersマッピング内の、msg.senderに対応するUser構造体の、nameプロパティを更新
users[msg.sender].name = _newName;
}
// 自分のユーザー情報を取得する関数
function getMyProfile() public view returns (User memory) {
// 自分のアドレスをキーに、User構造体を丸ごと返す
return users[msg.sender];
}
users[msg.sender].nameという書き方、とても直感的で分かりやすいですよね。もしstructを使わなかったら、userNames[msg.sender]のように別のマッピングを操作する必要があり、コードが複雑になっていたでしょう。
まとめ:整理整頓されたデータこそ力
お疲れ様でした!今回は、関連するデータを一つにまとめるstructと、それをmappingと組み合わせるという、Solidityにおけるデータ設計の基本にして最も重要なテクニックを学びました。
structを使うと、あなただけのカスタムデータ型を定義できる。mapping(キー => 構造体)のパターンは、複雑な情報をユーザーごとに管理するための王道である。- 構造体の各要素には、**ドット(
.)**を使ってアクセスする。
mappingとstructを自在に操れるようになったあなたは、もはや単なるSolidityの学習者ではありません。複雑な要件を持つ、本格的な分散型アプリケーションのデータ層を設計できる、アーキテクトへの道を歩み始めたのです。
さて、あなたのコントラクトは、ユーザーを登録し、そのデータを更新できるようになりました。しかし、その変化はブロックチェーンの内部だけで起きており、外部の世界からはその瞬間を捉えることができません。あなたのウェブサイトは、どうやって「たった今、新しいユーザーが登録された」ことを知ればよいのでしょうか?
次回、**第9話「ブロックチェーンに記録を残す!「イベント (event)」で何が起きたか通知しよう」**では、コントラクト内部で起きた重要な出来事を、外部のアプリケーションに通知するための仕組み、「イベント」について学びます。
-

-
Solidity学習講座:最終版 目次(全20話)
基礎編 第1話:未来のインターネットへようこそ!Solidityとスマートコントラクトの全体像 第2話:準備は1分!ブラウザだけで開発できる「Remix IDE」の基本操作 第3話:記念すべき初コント ...
続きを見る

