これはコンパイルして動作します:
diff := projected.Minus(c.Origin)
dir := diff.Normalize()
これはしません(タイトルのエラーが発生します):
dir := projected.Minus(c.Origin).Normalize()
誰かが理由を理解するのを手伝ってくれる? (囲碁学習)
これらのメソッドは次のとおりです。
// Minus subtracts another vector from this one
func (a *Vector3) Minus(b Vector3) Vector3 {
return Vector3{a.X - b.X, a.Y - b.Y, a.Z - b.Z}
}
// Normalize makes the vector of length 1
func (a *Vector3) Normalize() Vector3 {
d := a.Length()
return Vector3{a.X / d, a.Y / d, a.Z / d}
}
Vector3.Normalize()
メソッドにはpointerレシーバーがあるため、このメソッドを呼び出すには、_Vector3
_値へのポインターが必要です(_*Vector3
_)。最初の例では、Vector3.Minus()
の戻り値を変数__Vector3
_に格納します。
Goの変数はアドレス指定可能であり、diff.Normalize()
を記述する場合、これはショートカットであり、コンパイラーはdiff
変数のアドレスを自動的に取得して、タイプ_*Vector3
_の必要なレシーバー値を順番に取得しますNormalize()
を呼び出します。したがって、コンパイラはそれを次のように「変換」します
_(&diff).Normalize()
_
詳細は Spec:Calls: にあります
メソッドの呼び出し
x.m()
は、x
の メソッドセット がm
を含み、m
のパラメーターリストに引数リストを割り当てることができる場合に有効です。x
が addressable であり、_&x
_のメソッドセットにm
が含まれている場合、x.m()
は_(&x).m()
_の省略形です。
2番目の例が機能しない理由は、関数とメソッドの呼び出しの戻り値がアドレス指定できないため、コンパイラーがここでも同じですが、コンパイラはVector3.Minus()
呼び出しの戻り値のアドレスを取得できません。
アドレス指定可能なものは 仕様:アドレス演算子: に正確にリストされています
オペランドはaddressableでなければなりません。つまり、変数、ポインターの間接指定、またはスライスのインデックス付け操作のいずれかです。または、アドレス可能な構造体オペランドのフィールドセレクタ。または、アドレス可能な配列の配列インデックス操作。アドレス指定要件の例外として、
x
[_&x
_の式の中の]も(括弧で囲まれている可能性があります) 複合リテラル です。
関連する質問を参照してください:
操作の結果への参照をGoに保存するにはどうすればよいですか?
「最も簡単な」(変更が最も少ない)のは、単に変数に割り当て、その後にメソッドを呼び出すことです。これが最初の実用的なソリューションです。
もう1つの方法は、メソッドを変更して(ポインターレシーバーの代わりに)値レシーバーを持つことです。これにより、メソッドの戻り値のアドレスを取得する必要がなくなり、呼び出しを「連鎖」させることができます。メソッドがレシーバーを変更する必要がある場合、これは実行できない可能性があることに注意してください。これは、それがポインターである場合にのみ可能です(レシーバーは他のパラメーターと同じように-コピーを作成することによって渡されるため、それがポインターではない場合) 、コピーのみを変更できます)。
別の方法は、_*Vector3
_ではなくポインタ(_Vector3
_)を返すように戻り値を変更することです。戻り値が既にポインターである場合、ポインターレシーバーを必要とするメソッドへのレシーバーとしてはそのままなので、アドレスを取得する必要はありません。
また、アドレスを返す単純なヘルパー関数を作成することもできます。次のようになります。
_func pv(v Vector3) *Vector3 {
return &v
}
_
それを使う:
_dir := pv(projected.Minus(c.Origin)).Normalize()
_
これは_Vector3
_のメソッドである場合もあります。例:
_func (v Vector3) pv() *Vector3 {
return &v
}
_
そしてそれを使う:
_dir := projected.Minus(c.Origin).pv().Normalize()
_
いくつかの注意事項:
タイプが3つの_float64
_値のみで構成されている場合、パフォーマンスに大きな違いはありません。ただし、レシーバーと結果のタイプについて一貫している必要があります。ほとんどのメソッドにポインターレシーバーがある場合は、それらすべてにポインターレシーバーが必要です。ほとんどのメソッドがポインターを返す場合、すべてのポインターが返されます。
受け入れられた答えは本当に長いので、私を助けたものを投稿します:
この行に関してこのエラーが発生しました:
services.HashingServices{}.Hash("blabla")
だから私はそれを次のように変更しました:
(&services.HashingServices{}).Hash("blabla")