ホームページ  >  記事  >  バックエンド開発  >  Go プログラムでのインターフェイス呼び出しが失敗するのはなぜですか?

Go プログラムでのインターフェイス呼び出しが失敗するのはなぜですか?

WBOY
WBOYオリジナル
2023-06-10 09:18:06903ブラウズ

Go 言語は、その高速かつ効率的な機能により、世界で最も人気のあるプログラミング言語の 1 つになりました。インターフェイスは Go 言語の強力な機能であり、プログラマーに異なる構造間でやり取りおよび通信するための非常に洗練された方法を提供します。ただし、インターフェイス呼び出しが失敗すると、これは一部の初心者プログラマにとってよくある問題です。この記事では、インターフェイス呼び出しが失敗する理由を調査し、いくつかの解決策を提供します。

  1. 非ポインター インターフェイス

Go 言語では、通常、データが関数に渡されると、データは関数のパラメーターにコピーされます。また、インターフェイスを関数にパラメーターとして渡すとき、インターフェイス型の値がポインター型でない場合は、値型としてコピーされます。これにより、場合によってはインターフェイス呼び出しが失敗する可能性があります。

インターフェイス呼び出しは、インターフェイス値のメソッドを呼び出すことによって実現されます。メソッドはポインター上で動作する必要があるため、インターフェイス値の型がポインター型である必要があります。非ポインター型の値をインターフェイスに割り当てると、Go 言語は内部データをコピーし、新しいインターフェイス値を作成します。ただし、この新しいインターフェイス値はポインター型ではなくなるため、この新しいインターフェイス値でメソッドを直接呼び出すことはできません。これが、インターフェイス呼び出しが失敗する理由です。

したがって、インターフェイスを呼び出して、それらが適切に動作することを確認したい場合は、インターフェイスの型の値がポインター型であることを確認する必要があります。

  1. インターフェース型の不一致

Go 言語では、変数がインターフェース型でない場合、その変数をインターフェース型に割り当てることはできません。これは、インターフェイスが動的型であり、コンパイラによってチェックできないためです。インターフェイスのタイプが一致しない場合、インターフェイスの呼び出しも失敗します。次の例を見てください:

type Employee struct {
    Name string
    Age  int
}

func (e Employee) ShowName() {
    fmt.Printf("Name is %s
", e.Name)
}

func showName(s interface{}) {
    s.ShowName()
}

func main() {
    emp := Employee{Name: "John", Age: 25}
    showName(emp)
}

上記のコードは次のエラーを生成します:

cannot use emp (type Employee) as type interface {} in argument to showName:
  Employee does not implement interface {} (missing ShowName method)

Go コンパイラーは、この Employee 型は別の型であると認識するため、直接割り当てることはできません。インターフェース型変数。{}この問題を解決するには、Employee タイプを変更して必要なインターフェイスを実装し、それをパラメータとして showName 関数に渡すことができます。

  1. 不完全なインターフェイスの実装

もう 1 つのよくあるインターフェイス呼び出しの失敗は、不完全なインターフェイスの実装です。つまり、これは、構造体型にインターフェイスを実装しますが、インターフェイスのすべてのメソッドを実装するわけではないことを意味します。これにより、インターフェイス呼び出しを行うときにエラーが発生する可能性があります。次の例を見てください:

type Square struct {
    Side int
}

func (s Square) Area() int {
    return s.Side * s.Side
}

type Shape interface {
    Area() int
}

func PrintArea(s Shape) {
    fmt.Println("Area is", s.Area())
}

func main() {
    sq := Square{Side: 5}
    PrintArea(sq)
}

上記のコードは次のエラーを生成します:

cannot use sq (type Square) as type Shape in argument to PrintArea:
        Square does not implement Shape (missing Area method)

この例では、Square 型と Shape インターフェイスを定義します。 SquareタイプにAreaメソッドを実装しました。ただし、Shape インターフェイスの他のメソッドは実装しません。これにより、PrintArea 関数でのインターフェイス呼び出しが失敗します。したがって、インターフェイス呼び出しが成功できるように、インターフェイスのすべてのメソッドが指定された型で実装されていることを確認してください。

  1. インターフェースは nil 値でオーバーライドされます

Go 言語では、インターフェースに nil 値を割り当てることができます。これは、インターフェイスでは nil 値を有効な値として渡すことができることを意味します。ただし、これによりインターフェイス呼び出しが失敗する可能性もあります。

インターフェース値が nil の場合、そのインターフェースでメソッドを呼び出すと実行時エラーが発生します。次の例を見てください:

type Calculator interface {
    Add(a int, b int) int
}

func main() {
    var c Calculator
    fmt.Println(c.Add(1, 2))
}

上記のコードは次のエラーを生成します:

panic: runtime error: invalid memory address or nil pointer dereference

解決策は、nil 値インターフェイスを使用する前に、インターフェイス タイプが完全に実装されているか、Type アサーションを使用してインターフェイスが nil でないかどうかを判断できます。

func main() {
    var c Calculator
    if c != nil {
        fmt.Println(c.Add(1, 2))
    }
}
  1. インターフェイス呼び出しのシーケンス

Go 言語では、非ポインター型の値をインターフェイスに割り当てると、Go は内部データをコピーし、新しいインターフェース値。この新しいインターフェイス値も、同じ値を持つ別のインターフェイスです。したがって、インターフェイス内でメソッドを呼び出す場合は、プリミティブ型の値またはプリミティブ値へのポインター型を使用してインターフェイスの外でメソッド呼び出しを行う必要があります。

次の例を見てください:

type Employee struct {
    Name string
    Age  int
}

func (e Employee) ShowName() {
    fmt.Printf("Name is %s
", e.Name)
}

type NameShower interface {
    ShowName()
}

func main() {
    emp := Employee{Name: "John", Age: 25}
    var ns NameShower
    ns = emp
    ns.ShowName()

    pemp := &Employee{Name: "Doe", Age: 30}
    ns = pemp
    ns.ShowName()
}

上記のコードでは、Employee タイプと NameShower インターフェイスを定義します。 emp を作成して ns に割り当てると、emp はプリミティブ値へのポインター型ではないため、インターフェイス呼び出しは失敗します。 ShowName メソッドを呼び出すには、emp へのポインターを使用する必要があります。

pemp を作成して ns に割り当てると、pemp はプリミティブ値を指すポインター型であるため、インターフェイス呼び出しは成功します。したがって、インターフェイス呼び出しを行う前に、正しい型を使用していることを確認してください。

結論

この記事を通じて、Go プログラムでインターフェイス呼び出しが失敗する理由はすでにわかりました。次に、要約しましょう:

  • ポインタ型の値を必ずインターフェイスに割り当ててください。
  • インターフェイスのすべてのメソッドが指定された型に実装されていることを確認してください。
  • インターフェースを呼び出す前の値が nil ではないことを確認するか、型アサーションを使用してインターフェースが nil 値ではないことを確認してください。
  • インターフェイスでのメソッド呼び出しにポインター以外の型の値を使用する場合は、必ず正しい型を使用してください。

上記の方法に従えば、Go プログラムのインターフェイス呼び出しは失敗しません。

以上がGo プログラムでのインターフェイス呼び出しが失敗するのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。