[解決済み】XがYを実装していない(...メソッドがポインタのレシーバを持つ)
質問
この件に関するQ&Aはすでにいくつかあります。 XはYを実装していない(...メソッドにポインタレシーバーがある)。 しかし、私には、それらは異なることを話しているように見え、私の特定のケースには当てはまらないように思えます。
このエラーが発生するケースはいくつかあるようなのですが、どなたかまとめていただけませんか?
つまり、問題を回避する方法と、問題が発生した場合、どのような可能性があるかということです。Thx.
解決方法は?
このコンパイル時のエラーは、以下のような場合に発生します。 コンクリート 型がインターフェイスを実装していない場合。 型へのポインタ .
簡単な要約です。 An 割り当て は、代入される値が代入先のインタフェースを実装している場合に有効です。もし、その メソッドセット はインターフェイスのスーパーセットです。ポインタ型のメソッドセットには 両方とも ポインタのレシーバと非ポインタのレシーバがあります。非ポインタ型のメソッド群 のみ には、非ポインタのレシーバを持つメソッドが含まれます。
例を見てみましょう。
type Stringer interface {
String() string
}
type MyType struct {
value string
}
func (m *MyType) String() string { return m.value }
は
Stringer
インタフェース型は、1つのメソッドのみを持ちます。
String()
. インターフェイスの値に格納されるすべての値
Stringer
はこのメソッドを持たなければなりません。また、私たちは
MyType
を作成し、メソッド
MyType.String()
で
ポインタ
受信機です。これは
String()
メソッドは
メソッドセット
の
*MyType
の型にはありませんが
MyType
.
の値を割り当てようとすると
MyType
型の変数に
Stringer
というエラーが発生します。
m := MyType{value: "something"}
var s Stringer
s = m // cannot use m (type MyType) as type Stringer in assignment:
// MyType does not implement Stringer (String method has pointer receiver)
しかし、このような型に値を割り当てる場合は、すべて問題ありません。
*MyType
を
Stringer
:
s = &m
fmt.Println(s)
そして、期待通りの結果が得られます(試しに 囲碁プレイグラウンド ):
something
つまり、このコンパイルタイムエラーが発生するための条件です。
- の値 ポインタでない 代入される(あるいは渡される、あるいは変換される)具体的な型
- 代入される(あるいは渡される、あるいは変換される)インターフェース型
- 具象型は、インターフェースの必須メソッドを持つが、そのメソッドに ポインタレシーバ
問題解決のための可能性
- 値へのポインタを使用する必要があり、そのメソッドセットにはポインタのレシーバを持つメソッドが含まれます。
- または、レシーバタイプを 非ポインタ そのため、非ポインタ具象型のメソッドセットもそのメソッドを含むことになります (したがって、インターフェイスを満たすことになります)。メソッドが値を変更しなければならない場合、非ポインタのレシーバはオプションではないので、これは実行可能かもしれませんし、そうでないかもしれません。
構造体とエンベッディング
を使用する場合
構造体とエンベッディング
インターフェイスを実装する(メソッドの実装を提供する)のは、多くの場合、quot;you" ではなく、あなたの
struct
. この例のように。
type MyType2 struct {
MyType
}
m := MyType{value: "something"}
m2 := MyType2{MyType: m}
var s Stringer
s = m2 // Compile-time error again
のメソッドセットであるため、ここでもコンパイル時のエラーとなります。
MyType2
には
String()
メソッドを埋め込むことができます。
MyType
のメソッドセットのみです。
*MyType2
ということで、以下のように動作します(試しに
囲碁の遊び場
):
var s Stringer
s = &m2
を埋め込めば、うまくいくはずです。
*MyType
のみを使用し
非ポインタ
MyType2
(で試してみてください)。
囲碁の遊び場
):
type MyType2 struct {
*MyType
}
m := MyType{value: "something"}
m2 := MyType2{MyType: &m}
var s Stringer
s = m2
また、何を埋め込んでも(
MyType
または
*MyType
) を使用する場合、ポインタ
*MyType2
で試してみてください。
囲碁の遊び場
):
type MyType2 struct {
*MyType
}
m := MyType{value: "something"}
m2 := MyType2{MyType: &m}
var s Stringer
s = &m2
仕様書の関連部分(セクション 構造タイプ ):
構造体型が与えられた場合
S
という名前の型とT
の場合、以下のように構造体のメソッドセットに昇格メソッドが含まれます。
- もし
S
は匿名フィールドを含むT
のメソッドセットはS
と*S
は、レシーバを持つプロモートされたメソッドを含んでいます。T
. のメソッドセットは*S
は、レシーバを持つプロモートされたメソッドも含みます。*T
.- もし
S
は匿名フィールド*T
のメソッドセットはS
と*S
は、レシーバを持つプロモートされたメソッドを含んでいます。T
または*T
.
つまり、言い換えれば、非ポインタの型を埋め込んだ場合、非ポインタの埋め込み側のメソッドセットは、非ポインタのレシーバを持つメソッドだけを(埋め込み型から)取得する、ということです。
ポインタ型を埋め込んだ場合、非ポインタ型のエンベッダーのメソッドセットは、ポインタと非ポインタの両方のレシーバを持つメソッドを(埋め込まれた型から)取得します。
エンベッダーにポインターの値を使った場合、エンベッダーの型がポインターであろうとなかろうと、そのポインターのメソッドセットは常にポインターと非ポインターの両方のレシーバーを持つメソッドを(エンベッダーの型から)取得することになるのです。
注意してください。
非常に似たようなケースで,インターフェイスの値が
MyType
を実行しようとすると
タイプアサート
別のインターフェースの値を取得します。
Stringer
. この場合、上記の理由によりアサーションは成立しませんが、若干異なるランタイムエラーが発生します。
m := MyType{value: "something"}
var i interface{} = m
fmt.Println(i.(Stringer))
ランタイムパニック(で試してみてください。 囲碁プレイグラウンド ):
panic: interface conversion: main.MyType is not main.Stringer:
missing method String
タイプアサートの代わりに変換しようとすると、我々が話しているようなコンパイル時エラーが発生します。
m := MyType{value: "something"}
fmt.Println(Stringer(m))
関連
-
[解決済み] Luaにポインタのようなものはありますか?
-
[解決済み] C - エラーは "free(): invalid next size (normal)" です。
-
[解決済み] ポインタの「デリファレンス」とはどういう意味ですか?
-
[解決済み] パラメータと戻り値におけるポインタと値の比較
-
[解決済み】XがYを実装していない(...メソッドがポインタのレシーバを持つ)
-
[解決済み] 「<type>はインターフェースへのポインターであり、インターフェースではない」混乱
-
[解決済み] バリューレシーバー vs. ポインターレシーバー
-
[解決済み] Goで*int64をリテラルにするにはどうしたらいいですか?
-
[解決済み] ファットポインターとは何ですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン