English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Golang 基礎チュートリアル

Golang 制御文

Golang ファンクション & メソッド

Golang 構造体

Golang スライス & 配列

Golang 文字列(String)

Golang ポインタ

Golang インターフェース

Golang 并行

Golang エラ(Error)

Golang その他の雑多

Go 言語のインターフェース(Interfaces)

Go言語のインターフェースは他の言語とは異なります。Go言語では、インターフェースはカスタムタイプであり、1つまたは複数のメソッドシグネチャを指定するために使用されます。インターフェースは抽象的であるため、インターフェースのインスタンスを作成することはできません。ただし、インターフェースタイプの変数を作成し、その変数にインターフェースが必要なメソッドを持つ具体的なタイプの値を割り当てることができます。つまり、インターフェースはメソッドの集合であり、カスタムタイプでもあります。

インターフェースを作成する方法は?

Go言語では、以下の構文を使用してインターフェースを作成できます:

type interface_name interface{
    //メソッドシグネチャ
}

例えば:

//インターフェースの作成
type myinterface interface{
    // メソッド
    fun1() int
    fun2() float64
}

ここでは、インターフェース名がtypeとinterfaceキーワードの間に含まれており、メソッドシグネチャが括弧で囲まれています。

インターフェースを実現する方法は?

Go言語では、インターフェースを実現するには、インターフェースで宣言されたすべてのメソッドを実現する必要があります。Go言語のインターフェースは暗黙的に実現されます。他の言語と同様に、インターフェースを実現するための特定のキーワードを含んでいません。以下の例を参照してください:

// Golangプログラムは以下のように説明しています
//インターフェースの実現
package main
import "fmt"
//インターフェースの作成
type tank interface {
    // メソッド
    Tarea() float64
    Volume() float64
}
type myvalue struct {
    radius float64
    height float64
}
//実現方法
//タンク(Tank)インターフェース
func (m myvalue) Tarea() float64 {
    return 2*m.radius*m.height + 2*3.14*m.radius*m.radius
}
func (m myvalue) Volume() float64 {
    return 3.14 * m.radius * m.radius * m.height
}
func main() {
    // バケツのインターフェースを使用してアクセス
    var t tank
    t = myvalue{10, 14}
    fmt.Println("バケツの面積 :", t.Tarea())
    fmt.Println("バケツの容量:", t.Volume())
}

出力:

バケツの面積 : 908
バケツの容量: 4396

注意事項

  • インターフェースのゼロ値はnilです。

  • インターフェースがメソッドを含んでいない場合、このようなインターフェースは空インターフェースと呼ばれます。したがって、すべての型は空インターフェースを実装します。

    構文:

    interface{}
  • インターフェースの型:このインターフェースには2種類の型があります。一つは静的なもので、もう一つは動的なものです。静的な型はインターフェース自身です。例えば、以下の例のtankですが、インターフェースには静的な値はありませんので、常に動的类型を指しています。
    インターフェースの型の変数は、インターフェースを実装する型の値を含んでおり、その値は動的类型と呼ばれ、その型は動的类型です。また、具体的な値と具体的な型と呼ばれます。

    //Goプログラムの概念の説明
    //動的类型と型
    package main
    import "fmt"
    //インターフェースの作成
    type tank interface {
        // メソッド
        Tarea() float64
        Volume() float64
    }
    func main() {
        var t tank
        fmt.Println("tankインターフェースの値は: ", t)
        fmt.Printf("tankの型は: %T ", t)
    }

    出力:

    tankインターフェースの値は: <nil>
    tankの型は: <nil>

    上記の例では、tankという名前のインターフェースがあります。この例では、fmt.Println("tankインターフェースの値は: ", t) このステートメントはインターフェースの動的类型を返しますが、fmt.Printf("tankの型は: %T ", t)のステートメントはインターフェースの動的类型を返します、つまりnil、この場合、インターフェースは誰が実装しているかを知りません。

  • 型宣言:Go言語では、型宣言はインターフェースの値に適用されます。別の言い方をすると、型宣言はインターフェースの値を抽出するプロセスです。

    構文:

    a.(T)

    ここでは、aはインターフェースの値または式であり、Tは型宣言と呼ばれる型です。型宣言は、操作数の動的型が宣言された型に一致するかどうかを確認するために使用されます。Tが具体的な型である場合、型宣言はaの与えられた動的类型がTに等しいかどうかを確認し、ここで、確認が成功すると、型宣言はaの動的类型を返します。それどころか、確認が失敗すると、操作はpanic例外が発生します。Tがインターフェース型である場合、型宣言はTに一致する与えられた動的类型を確認し、ここで、確認が成功すると、動的类型を抽出しません。

    //タイプアサーション 
    package main 
      
    import "fmt"
      
    func myfun(a interface{}) { 
      
        //aの値を抽出
        val := a.(string) 
        fmt.Println("値: ", val) 
    } 
    func main() { 
      
        var val interface { 
        } = "w3codebox"
          
        myfun(val) 
    }

    出力:

    値:  w3codebox

    上記の例では、val:= a。(string)文は以下のように変更されますval:= a。(int)、プログラムはpanic例外を投げます。したがって、この問題を避けるために、以下の構文を使用します:

    value, ok := a.(T)

    ここでは、aのタイプがTに等しい場合、この値はaの動的値を含み、okはtrueに設定されます。また、aのタイプがTに等しくない場合、okはfalseに設定され、値はゼロ値を含み、プログラムはpanic例外を投げません。以下のプログラムを参照してください:

    package main
    import "fmt"
    func myfun(a interface{}) {
        value, ok := a.(float64)
        fmt.Println(value, ok)
    }
    func main() {
        var a1 interface {
        } = 98.09
        myfun(a1)
        var a2 interface {
        } = "w3codebox"
        myfun(a2)
    }

    出力:

    98.09 true
    0 false
  • タイプ判定:Goのインターフェースでは、タイプ判定はインターフェースの具体的なタイプをcase文で提供された複数のタイプと比較するために使用されます。これはタイプ宣言に似ていますが、大文字と小文字の指定が値ではなくタイプにあります。また、タイプとインターフェースタイプを比較することもできます。以下の例を参照してください:

    package main
    import "fmt"
    func myfun(a interface{}) {
        //タイプ判定を使用
        switch a.(type) {
        case int:
            fmt.Println("タイプ: int、値:", a.(int))
        case string:
            fmt.Println("\nタイプ: string、値: ", a.(string))
        case float64:
            fmt.Println("\nタイプ: float64、値: ", a.(float64))
        default:
            fmt.Println("\nタイプが見つかりません")
        }
    }

    出力:

    タイプ: string、値:  w3codebox
    タイプ: float64、値:  67.9
    タイプが見つかりません
  • インターフェースの使用:異なるタイプのパラメータを渡したいメソッドや関数では、インターフェースを使用できます。例えば、Println()関数のように。また、同じインターフェースを実装する複数のタイプがある場合にも、インターフェースを使用できます。