カテゴリ: Go言語 更新日: 2025/12/11

Go言語のインターフェースとコンポジションの基本設計例を学ぶ

Go言語のインターフェースとコンポジションの基本設計例
Go言語のインターフェースとコンポジションの基本設計例

先生と生徒の会話形式で理解しよう

生徒

「先生、Go言語でインターフェースを使ったコンポジションって何ですか?」

先生

「コンポジションとは、複数の機能を持つ小さな部品を組み合わせて、新しい機能を作る設計方法です。インターフェースと組み合わせることで柔軟な設計が可能になります。」

生徒

「部品を組み合わせるって、具体的にはどういうイメージですか?」

先生

「例えば車を作るとき、エンジンやタイヤやハンドルといった部品を組み合わせます。部品自体が別々に動作しても、車としての動きは一つにまとめられます。これがコンポジションの考え方です。」

生徒

「なるほど、コードでも同じように部品を組み合わせるんですね。」

先生

「その通りです。それではGo言語での基本的な実装例を見てみましょう。」

1. インターフェースとコンポジションの基本

1. インターフェースとコンポジションの基本
1. インターフェースとコンポジションの基本

Go言語では、構造体に機能を追加する際にコンポジションを使います。インターフェースは、どの構造体にも共通の操作を約束として定義するものです。コンポジションを使うと、複数の構造体を組み合わせて新しい構造体を作ることができます。

2. インターフェースを使った抽象化

2. インターフェースを使った抽象化
2. インターフェースを使った抽象化

共通の動作を抽象化することで、異なる構造体でも同じ操作で扱えるようになります。例えば「Speaker」というインターフェースを作ると、犬も猫も同じSpeakメソッドで鳴く動作を扱えます。


type Speaker interface {
    Speak()
}

type Dog struct{}
type Cat struct{}

func (d Dog) Speak() {
    fmt.Println("ワンワン")
}

func (c Cat) Speak() {
    fmt.Println("ニャー")
}

3. コンポジションで機能を組み合わせる

3. コンポジションで機能を組み合わせる
3. コンポジションで機能を組み合わせる

次に、車の例を使ってコンポジションを実装します。エンジンとタイヤを部品として組み込み、車としてまとめます。


type Engine struct{}

func (e Engine) Start() {
    fmt.Println("エンジン始動")
}

type Tire struct{}

func (t Tire) Rotate() {
    fmt.Println("タイヤ回転")
}

type Car struct {
    Engine
    Tire
}

func main() {
    myCar := Car{}
    myCar.Start()  // Engineのメソッド
    myCar.Rotate() // Tireのメソッド
}

このように、Car構造体はEngineとTireを持つことで、それぞれの機能をまとめて利用できます。これがGo言語におけるコンポジションの基本です。

Go言語を基礎からスッキリ学びたい人や、 文法だけでなく「実用的な使い方」まで押さえたい人には、 定番の入門書がこちらです。

基礎からわかるGo言語をAmazonで見る

※ Amazon広告リンク

4. インターフェースとコンポジションを組み合わせる設計

4. インターフェースとコンポジションを組み合わせる設計
4. インターフェースとコンポジションを組み合わせる設計

インターフェースを使って共通の動作を抽象化し、コンポジションで部品を組み合わせると柔軟で拡張性の高い設計が可能です。


type Movable interface {
    Move()
}

type EngineMovable struct{}

func (e EngineMovable) Move() {
    fmt.Println("エンジンで移動")
}

type TireMovable struct{}

func (t TireMovable) Move() {
    fmt.Println("タイヤで移動")
}

type Vehicle struct {
    Movable
}

func main() {
    car := Vehicle{Movable: EngineMovable{}}
    car.Move()

    bike := Vehicle{Movable: TireMovable{}}
    bike.Move()
}

Vehicle構造体はMovableインターフェースを持つことで、移動方法を自由に差し替えられます。これにより、新しい部品や機能を追加しても既存のコードを変更せずに済みます。

5. 設計の利点

5. 設計の利点
5. 設計の利点
  • 再利用可能な部品を作ることで開発効率が上がる
  • コードの柔軟性と拡張性が向上する
  • 異なる構造体でも同じ操作で扱える
  • プログラム全体の設計がシンプルで理解しやすくなる

Go言語のインターフェースとコンポジションを組み合わせることで、複雑な機能も整理して、安全で拡張性のあるプログラム設計が可能です。

まとめ

まとめ
まとめ

ここまで、Go言語におけるインターフェースとコンポジションの基本的な仕組みや考え方を、日常の例や具体的なコードとともに学んできました。 インターフェースは「どんな動作ができるのか」という共通点を示し、コンポジションは「必要な部品を組み合わせて機能を構築する」という設計思想です。 これら二つを組み合わせることで、プログラム全体の見通しが良くなり、柔軟に拡張できる構造を作れる点がGo言語の大きな魅力だといえます。 特に、インターフェースを実装することで、異なる構造体が同じ動作を持つという統一感が生まれ、コンポジションにより構造体同士を自然に組み合わせられるため、 初心者でもわかりやすく扱いやすいコードが実現できます。

また、コンポジションとインターフェースを組み合わせた設計は、システムが成長したときに真価を発揮します。 部品を交換するように機能を差し替えられるため、将来的な変更にも対応しやすく、既存のコードに手を入れることなく新しい機能を追加することができます。 これは、長く運用されるアプリケーションにおいてとても重要な性質であり、Goが多くのエンジニアに支持される理由でもあります。

以下では、今回学んだ内容をひとまとめにするために、インターフェースとコンポジションの理解を深めるもう一つの例を紹介します。 このサンプルは、実際の開発でもよく登場する「ログ出力」をテーマにしたものです。 異なるログ方法を統一したインターフェースで扱い、コンポジションを用いて柔軟に組み合わせられる設計を体験してみましょう。

ログ出力を題材にしたまとめサンプル

// ログ出力の共通インターフェース
type Logger interface {
    Log(message string)
}

// コンソールにログを表示する部品
type ConsoleLogger struct{}

func (c ConsoleLogger) Log(message string) {
    fmt.Println("コンソールログ:", message)
}

// ファイルにログを保存する部品
type FileLogger struct{}

func (f FileLogger) Log(message string) {
    fmt.Println("ファイルログ:", message)
}

// コンポジションで組み合わせる構造体
type Application struct {
    Logger
}

func main() {
    // 動作の差し替えが容易
    app1 := Application{Logger: ConsoleLogger{}}
    app1.Log("アプリケーション開始")

    app2 := Application{Logger: FileLogger{}}
    app2.Log("設定ファイルを読み込みました")
}

この例では、アプリケーションがどのようにログを出力するかを、インターフェースを通じて自由に切り替えられる設計になっています。 コンポジションを使うことで、さまざまな動作を自然に組み合わせられ、同じ役割を持つ部品であればどれでも簡単に入れ替えられます。 こういった柔軟な設計を身につけることで、Go言語による開発がより快適で効率的なものになるでしょう。

先生と生徒の振り返り会話

生徒

「先生、インターフェースとコンポジションを組み合わせると、こんなに柔軟な設計ができるんですね!」

先生

「そうだね。共通の動作をインターフェースでまとめ、機能の組み合わせをコンポジションで行うことで、コードの再利用性が高まり、変更にも強くなるんだ。」

生徒

「車の例もログの例も、とても分かりやすかったです。同じメソッド名で扱えるのが便利ですね。」

先生

「その通り。Go言語はシンプルな仕組みで強力な設計ができるのが魅力だよ。これからコードを書くときも“共通点を見つけて抽象化する”という視点を意識してみると良いね。」

生徒

「はい! 今日学んだ内容を使って、自分でも設計を工夫してみます!」

カテゴリの一覧へ
新着記事
New1
Go言語
Go言語の短絡評価(ショートサーキット)を使った条件式の工夫をやさしく解説!初心者でも理解できる基本知識
New2
Go言語
Go言語の構造体の初期化パターンとコンストラクタ的関数の書き方を徹底解説!初心者でもわかる基本と実用例
New3
Kotlin
Kotlinの例外処理とキャンセルの連携を完全ガイド!初心者でもわかるCoroutineExceptionHandlerの使い方
New4
Go言語
Go言語のクロージャとは?関数内関数の活用例と仕組み
人気記事
No.1
Java&Spring記事人気No1
Kotlin
KotlinのChannelでデータをやり取りする方法を完全ガイド!初心者にもわかる非同期通信の基本
No.2
Java&Spring記事人気No2
Go言語
Go言語でのDB接続情報を環境変数で管理する方法|初心者でも安全に設定
No.3
Java&Spring記事人気No3
Kotlin
Android Studioのインストール手順と初期設定を初心者向けに完全解説!
No.4
Java&Spring記事人気No4
Kotlin
Kotlinのビルド設定エラーと解決法まとめ!初心者向けGradleトラブル対処ガイド
No.5
Java&Spring記事人気No5
Kotlin
Gradleファイル(build.gradle.kts)の書き方と役割をやさしく解説!Kotlin初心者向け完全ガイド
No.6
Java&Spring記事人気No6
Kotlin
Kotlinでテキスト表示・編集!初心者でもわかるTextViewとEditTextの使い方
No.7
Java&Spring記事人気No7
Kotlin
Kotlin DSLとGroovy DSLの違いをやさしく解説!初心者でもわかるGradleスクリプトの使い分け
No.8
Java&Spring記事人気No8
Swift
Swift Playgroundの使い方を完全解説!初心者に最適な学習環境の始め方

💻 作業効率アップに

ノートPCを縦置きしてデスクを広く。
省スペースで片づく定番スタンド

UGREEN 縦型スタンドをAmazonで見る

※ Amazon広告リンク