見出し画像

golang interfaceとは 使い方と注意点について解説

今回はgolangのインタフェース(interface)について解説していきます。


interfaceとは

Go言語のインタフェースは、メソッドのセットを定義できる型です。

Go言語では継承がない代わりにインタフェースが使用され、オブジェクト指向の概念に則っています。

インターフェースを使うことで、「異なるものを同じように扱える」ようになります。


interfaceの使い方

「異なるものを同じように扱える」というのはどういうことでしょうか。サンプルコードを見ながら解説していきます。

例えば、支払い方法について考えてみましょう。
クレジットカード、デビットカード、電子マネーなど様々な支払い型があります。
それぞれ異なる方法で支払いを処理しますが、「支払いをする」という意味では共通の行動をします。

インターフェースを使うことで、この「支払いをする」という行動を表現することができます。「PaymentMethod」とインターフェースを作り、その中に「Pay」というメソッドを定義します。

このインターフェースは、どんな支払い方法においても「Pay」メソッドを持っていれば「PaymentMethod」として扱えるようできます。

type PaymentMethod interface {
    Pay(amount float64) string
}

そして、クレジットカード、デビットカード、電子マネーといった具体的な型を定義し、それぞれに「Pay」メソッドを実装することで、これらの支払い方法はすべて「PaymentMethod」インターフェースを実装したということになります。

type CreditCard struct {}
func (c CreditCard) Pay(amount float64) string {
    return fmt.Sprintf("Paid $%.2f with Credit Card", amount)
}

type DebitCard struct {}
func (d DebitCard) Pay(amount float64) string {
    return fmt.Sprintf("Paid $%.2f with Debit Card", amount)
}

type ElectronicMoney struct {}
func (e ElectronicMoney) Pay(amount float64) string {
    return fmt.Sprintf("Paid $%.2f with Electronic Money", amount)
}

このように書くことで、どの支払い方法においても「PaymentMethod」として扱うことができます。

func processPayment(p PaymentMethod, amount float64) {
    fmt.Println(p.Pay(amount))
}

このprocessPayment()関数は、クレジットカード、デビットカード、電子マネーを含むどんな「PaymentMethod」に対しても使うことができます。

つまり、異なる型(クレジットカード、デビットカード、電子マネー)を同じインターフェース(PaymentMethod)を通じて同じ方法(Payメソッドを呼び出す)で扱うことができるということになります。


interfaceの注意点

インターフェースは最小限に

インターフェースはできるだけ小さく保つ必要があります。
必要なメソッドのみインターフェースに含めることで、インターフェースをより汎用的かつ疎結合にすることができます。

良い例

type Reader interface {
    Read(p []byte) (n int, err error)
}

微妙な例

type FileOperations interface {
    Read(p []byte) (n int, err error)
    Write(p []byte) (n int, err error)
    Close() error
    Seek(offset int64, whence int) (int64, error)
    ...
    ...
    ...
}


空のインターフェースの使用に注意

空のインターフェース(interface{})には任意の型を受け入れることができますが、型安全性が失われます。
具体的なインターフェースを使用して、型安全性を保つようにしましょう。

具体的なインターフェースの例

type Printer interface {
    Print() string
}

func Print(p Printer) {
    fmt.Println(p.Print())
}


インターフェースの値がnilの場合

インターフェース型の変数がnilの場合、そのインターフェースのメソッドを呼び出すと、実行時にpacinを起こす可能性があります。

nilである可能性がある場合は、インターフェース値がnilかどうかをチェックするようにしましょう。


インターフェースの統合

複数のインターフェースを組み合わせて、1つのインターフェースを作成することができます。

このようにインターフェースの統合を行うことでコードの再利用性を高め、より柔軟な設計を可能になります。

type Reader interface {
    Read(p []byte) (n int, err error)
}

type Writer interface {
    Write(p []byte) (n int, err error)
}

type ReadWriter interface {
    Reader
    Writer
}


型アサーションと型スイッチ

インターフェース型の変数の元の型を知るためには型アサーションを使用します。

型アサーションの例

var i interface{} = "hello"

s, ok := i.(string)
if ok {
    fmt.Println(s)
}

型スイッチを使用すると、インターフェース値の型に基づいて異なるアクションを実行することができます。

型スイッチの例

var i interface{} = ...

switch v := i.(type) {
case int:
    fmt.Println("整数:", v)
case string:
    fmt.Println("文字列:", v)
default:
    fmt.Println("不明な型")
}


golangをもっと詳しくなりたい方に

初めてのGo言語

Go言語の入門から応用まではこの一冊で網羅されています。説明も順序立てて説明されており完成度の高い参考書となっています。


詳解Go言語Webアプリケーション開発

こちらはGo言語の基礎知識を得たあとに読むことをすすめる本となっています。ハンズオン形式で手を動かしながら実装をしていくことができるため、実際の開発を意識しながらGo言語を学ぶことができます。

以下の記事では他にも筆者が実際に読んでおすすめしたい本をまとめています。


【Go入門】Golang基礎入門 + 各種ライブラリ + 簡単なTodoWebアプリケーション開発(Go言語)

まだGo言語の勉強を始めていない方、全くの初心者の方にはこちらのUdemy教材が最もおすすめです。

この教材ではgolangの基礎について網羅的に学ぶことができます。ただ見て学ぶだけでなく、講座の中でアプリ作成まで行うことで学んだことの理解をさらに深めることができます。


現役シリコンバレーエンジニアが教えるGo入門 + 応用でビットコインのシストレFintechアプリの開発

個人的に最も勉強になったのは「現役シリコンバレーエンジニアが教えるGo入門 + 応用でビットコインのシストレFintechアプリの開発」という教材です。
本格的なレクチャーに入る前に、なぜGoなのか、なぜFintechなのかについて説明されていることで、Goの概念や意味について大枠から理解することができます。

以下の記事では筆者が実際に受講したおすすめUdemy教材をまとめています。

※本ページではアフィリエイトリンク(PR)が含まれています


この記事が参加している募集

この記事が気に入ったらサポートをしてみませんか?