😴

Goのinterfaceが意味不明な方へ

2022/10/19に公開

Go の interface に関して、極力シンプルに簡単な言葉で解説します。

対象者

  • interface をググってもなかなか理解出来ない
  • 外部ライブラリを用いて開発中に、interface が出て戸惑った
  • コンストラクタ関数、初期化とは何か分からない

interface 型を使うまでの準備

まず interface と出てきますがこれはです。
値と型の区別をしっかりとする必要があります。

例えば

  var name string // string`型`のname変数です。

  name = "taro" // "taro"という`値`をname変数に代入します。

それでは本題に入ります。

  type error interface {
    Error() string
  }

上記のようなコードが Go ではよく interface の解説で出てきます。
type で始まっているようにこれは型の宣言です。
要するに error interface 型です。

この error interface 型を使うには、

中に書いてある Error() string というメソッドを、構造体型に実装してあげる必要があります。

まず構造体型に対して Error() stringメソッドを追加します。


// ここでは構造体型の宣言です。
 type myErr struct {
   message      string
}

// 上記の型に対してErrorメソッドを追加します。
func (e myErr) Error() string {
  return e.message
}

ここまで行うと、myErr 型(構造体型)は error 型(interface 型)としても
使用出来るようになります。

interface 型として使いたいなら、interface 型で求められているメソッドを
構造体型にそのメソッドを書いてあげれば、interface 型としても使えるよ!ということです。

interface 型を使う

上記までが理解出来たとして、ではそもそもこの error 型をどう実際のコードで使えるようになるのでしょうか。

まだただの型定義であり、この後使えるようにしないといけないです。

ではどうするかというと interface 型を実装している構造体型を初期化する必要があります。(インスタンス化)

初期化するが意味不明でも大丈夫です。

では、元々の構造体型を初期化します。

ここで良くコンストラクタ関数というものがよく出てくるので一緒に説明します。
コンストラクタ関数 = 初期化関数です。

初期化に関してですが、プログラミングにおける初期化は初めからにすることではないです。
宣言された変数に初めて値を代入することを指します。

とりあえずまだ型で宣言しただけなので、今から使えるようにします。ということです。

参考: 初期化とは
https://wa3.i-3-i.info/word12961.html

Go の慣習的に New から始まる関数名がコンストラクタ関数として作成します。


  // 戻り値で書くのは型です。
  // 先ほど作成した構造体型を使ってreturnで値を埋めてあげます。
  func NewMyErr(message string) *myErr {
   // 具体的な値を戻り値として返す
   return &myErr{message}
  }

  func main() {
    myErr := NewMyErr("エラーが発生しました")
    // ここのmyErrは値です。ここだと型は*myErr型(構造体型)です。同様にerror型(interface型)としても使えます。
  }

要するに上記で何が行われているかというと型に具体的な値を入れて、初期化をしています。

細かくいうとメモリ上に領域を確保して使えるようにします。

また return &myErr{message} というのは

  1. 構造体の初期化
  2. ポインタ化(=アドレスを返す)
  3. 元の関数への戻り値の返却(値を変数に入れてあげます)

を行なっています。

型を初期化したので使用出来る準備が整いました。

長くなりましたが変数 myErr は error 型(interface 型)として使うことが出来るようになります。

GitHubで編集を提案

Discussion