ホーム プログラミング言語 golang golang func Go 言語の関数型はインターフェイスを実装します – 関数をインターフェイスとして呼び出します






Go 言語の関数型はインターフェイスを実装します – 関数をインターフェイスとして呼び出します




 
 
関数は他の型と同様に「第一級市民」です。他の型もインターフェイスを実装でき、関数も同様に実装できます。このセクションでは、構造体と関数間のインターフェイスを実装するプロセスを比較します。

 

まず、このセクションの完全なコードを示します。

 package main

import (
    "fmt"
)

// インボーカーインターフェース
type Invoker interface {
    // Callメソッドを実装する必要があります
    Call(interface{})
}

// 構造体タイプ
type Struct struct {
}

// InvokerのCallを実装する
func (s *Struct) Call(p interface{}) {
    fmt.Println("from struct", p)
}

// 関数を型として定義する
type FuncCaller func(interface{})

// InvokerのCallを実装する
func (f FuncCaller) Call(p interface{}) {

    // f関数本体を呼び出す
    f(p)
}

func main() {

    // インターフェース変数を宣言する
    var invoker Invoker

    // 構造体インスタンスを作成する
    s := new(Struct)

    // インスタンス化された構造体をインターフェイスに割り当てる
    invoker = s

    // インターフェイスを使用してインスタンス化された構造体のメソッドStruct.Callを呼び出します
    invoker.Call("hello")

    // 無名関数をFuncCaller型に変換し、それをインターフェースに割り当てる
    invoker = FuncCaller(func(v interface{}) {
        fmt.Println("from function", v)
    })

    // インターフェースを使用してFuncCaller.Callを呼び出します。内部では、関数本体が呼び出されます。
    invoker.Call("hello")
} 

次のようなインターフェイスがあります。


type Invoker interface {
    Call(interface{})
} 

このインターフェイスは Call() メソッドを実装する必要があります。呼び出し時には、interface{} 型の変数が渡されます。この型の変数は任意の型の値を表します。

次に、インターフェイスの実装に構造体を使用します。

構造体はインターフェースを実装します

Invoker インターフェイスを実装するための構造体のコードは次のとおりです。

 // Structure Type
type Struct struct {
}

// Invokerの呼び出しを実装する
func (s *Struct) Call(p interface{}) {
    fmt.Println("from struct", p)
} 

コードの説明は次のとおりです。

  • 2行目は構造体を定義していますが、この例の構造体はメンバを必要とせず、主にInvokerの実装方法を示しています。
  • 6 行目の Call() は構造体のメソッドです。このメソッドの機能は、構造体の値と渡されたインターフェースの型を出力することです。{}

定義された Struct 型をインスタンス化し、それを呼び出し用のインターフェイスに渡します。コードは次のとおりです。


var invoker Invoker

s := new(Struct)

invoker = s

invoker.Call("こんにちは") 

コードの説明は次のとおりです。

  • 行 2 では、Invoker 型の変数を宣言しています。
  • 5 行目、 new を使用して構造体をインスタンス化します。この行は s:=&Struct としても記述できます。
  • 8 行目では、 の型は *Struct であり、Invoker インターフェイス型がすでに実装されているため、invoker への割り当ては成功しています。
  • 11行目ではインターフェースのCall()メソッドを通じてhelloが渡されており、このときStruct構造体のCall()メソッドが呼び出されます。

次に、機能の実装構造の違いを比較します。

コード出力は次のとおりです。

from struct こんにちは

関数の本体はインターフェイスを実装します

関数の宣言でインターフェイスを直接実装することはできません。関数が型として定義された後、その型を使用して構造体が実装されます。型メソッドが呼び出されるときは、関数本体を呼び出す必要があります。

 // Function is defined as a type
type FuncCaller func(interface{})

// Implementation of Invoker's Call
func (f FuncCaller) Call(p interface{}) {

    // Call the body of the f() function
    f(p)
} 

コードの説明は次のとおりです。

  • 2 行目では、func(interface{}) をタイプ FuncCaller として定義します。
  • 5 行目では、FuncCaller の Call() メソッドが Invoker の Call() メソッドを実装します。
  • 8行目では、func(interface{})に関係なくFuncCallerのCall()メソッドが呼び出されており、関数本体を手動で呼び出す必要があります。

上記のコードは関数の型のみを定義しており、関数自体によって論理的に処理する必要があります。FuncCaller をインスタンス化する必要はありません。関数を FuncCaller 型に変換するだけで済みます。関数のソースは名前付き関数にすることができます、匿名関数またはクロージャ。次のコードを参照してください。

 // Declare interface variable
var invoker Invoker

// Convert anonymous function to FuncCaller type, and then assign it to the interface
invoker = FuncCaller(func(v interface{}) {
    fmt.Println("from function", v)
})

// Use the interface to call FuncCaller.Call, which will invoke the underlying function
invoker.Call("hello") 

コードの説明は次のとおりです。

  • 2 行目ではインターフェース変数を宣言しています。
  • 5 行目では、func(v Interface{}){} 匿名関数が FuncCaller 型に変換されます (関数のシグネチャのみ変換可能)。このとき、FuncCaller 型は Invoker の Call() メソッドを実装し、呼び出し側インターフェイスへの割り当ては成功しました。
  • 10 行目、インターフェイス メソッド呼び出しを使用します。

コード出力は次のとおりです。

from function hello

HTTP パケットの例

HTTP パッケージにはハンドラー インターフェイスの定義が含まれており、コードは次のとおりです。

type handler interface {
    ServeHTTP(ResponseWriter, *Request)
} 

ハンドラーは、各 HTTP リクエストとレスポンスの処理を定義するために使用されます。

同時に、処理関数を使用してインターフェイスを実装することもできます。これは次のように定義されます。


func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
    f(w, r)
}

クロージャを使用してデフォルトの HTTP リクエスト処理を実装するには、次のように定義されている http.HandleFunc() 関数を使用できます。

 func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
    DefaultServeMux.HandleFunc(pattern, handler)
} 

DefaultServeMux は、次のように定義された HandleFunc() メソッドを持つ ServeMux 構造体です。

 func (mux *ServeMux) HandleFunc(pattern string, handler func
(ResponseWriter, *Request)) {
    mux.Handle(pattern, HandlerFunc(handler))
}

上記のコードは、外部から渡された関数 handler() を HandlerFunc 型に変換します。HandlerFunc 型は、Handler の ServeHTTP メソッドを実装します。基になる層は、さまざまな型を使用して、処理用の Handler インターフェイスを実装できます。

 

「 Go 言語の関数型はインターフェイスを実装します – 関数をインターフェイスとして呼び出します」についてわかりやすく解説!絶対に観るべきベスト2動画

GO言語でAPI開発「 gRPC 」入門
22 Golang チュートリアル – インターフェイス