広告

第8話:データを整理整頓!複雑な情報を扱う「構造体 (struct)」で独自データ型を作る

2025年7月31日

第8話:データを整理整頓!複雑な情報を扱う「構造体 (struct)」で独自データ型を作る

概要

mappingの能力を最大限に引き出す、Solidityの「構造体 (struct)」を徹底解説します。ユーザーID・名前・残高といった複数の関連データを、あなただけのオリジナルなデータ型にまとめる方法を学習。

mapping(address => User)という王道パターンを使い、複雑な情報を整理整頓し、本格的なDAppのデータ層を設計するスキルが身につきます。

目次
Solidity学習講座:最終版 目次(全20話)
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とは、複数の異なるデータ型を持つ変数を一つに束ねた、ユーザー定義の複合データ型です。uintstringがSolidityに組み込まれた基本データ型であるのに対し、structはあなたが自由に設計できるカスタムデータ型と言えます。

structの定義は非常にシンプルです。

Solidity

struct 構造体の名前 {
    データ型1 変数名1;
    データ型2 変数名2;
    // ... 必要なだけ変数を定義
}

先ほどのユーザー情報の例で、Userという名前のstructを定義してみましょう。

Solidity

struct User {
    uint id;
    string name;
    bool isMember;
    uint pointBalance;
}

これで、uintaddressなどと同じように、**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という見慣れないキーワードが出てきましたね。stringstructのような複雑なデータ型を関数の引数や関数内のローカル変数として使う場合、そのデータがどこに保存されるかを示す**「データロケーション」を指定する必要があります。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(キー => 構造体) のパターンは、複雑な情報をユーザーごとに管理するための王道である。
  • 構造体の各要素には、**ドット(.)**を使ってアクセスする。

mappingstructを自在に操れるようになったあなたは、もはや単なるSolidityの学習者ではありません。複雑な要件を持つ、本格的な分散型アプリケーションのデータ層を設計できる、アーキテクトへの道を歩み始めたのです。

さて、あなたのコントラクトは、ユーザーを登録し、そのデータを更新できるようになりました。しかし、その変化はブロックチェーンの内部だけで起きており、外部の世界からはその瞬間を捉えることができません。あなたのウェブサイトは、どうやって「たった今、新しいユーザーが登録された」ことを知ればよいのでしょうか?

次回、**第9話「ブロックチェーンに記録を残す!「イベント (event)」で何が起きたか通知しよう」**では、コントラクト内部で起きた重要な出来事を、外部のアプリケーションに通知するための仕組み、「イベント」について学びます。

目次
Solidity学習講座:最終版 目次(全20話)
Solidity学習講座:最終版 目次(全20話)

基礎編 第1話:未来のインターネットへようこそ!Solidityとスマートコントラクトの全体像 第2話:準備は1分!ブラウザだけで開発できる「Remix IDE」の基本操作 第3話:記念すべき初コント ...

続きを見る

-Solidity