sort パッケージ:
type Interface interface {
    Len() int
    Less(i, j int) bool
    Swap(i, j int)
}
...
type reverse struct {
    Interface
}
Interface構造体の匿名インターフェースの意味は何reverseですか?
sort パッケージ:
type Interface interface {
    Len() int
    Less(i, j int) bool
    Swap(i, j int)
}
...
type reverse struct {
    Interface
}
Interface構造体の匿名インターフェースの意味は何reverseですか?
回答:
このようにして、リバースはを実装しsort.Interface、他のすべてを定義することなく特定のメソッドをオーバーライドできます
type reverse struct {
        // This embedded Interface permits Reverse to use the methods of
        // another Interface implementation.
        Interface
}
ここでは、(j,i)代わりにスワップする方法に注意してください。(i,j)またreverse、reverse実装した場合でも、これが構造体に対して宣言された唯一のメソッドです。sort.Interface
// Less returns the opposite of the embedded implementation's Less method.
func (r reverse) Less(i, j int) bool {
        return r.Interface.Less(j, i)
}
このメソッド内で渡される構造体はreverseすべて、新しい構造体に変換します。
// Reverse returns the reverse order for data.
func Reverse(data Interface) Interface {
        return &reverse{data}
}
このアプローチが不可能だった場合に何をしなければならないかを考えると、真の価値が生まれます。
Reverseメソッドを追加しsort.Interfaceますこの変更には、標準のリバース機能を使用する数千のパッケージにわたって、さらに多くのコード行が必要になります。
reverse持っているメンバーのタイプのをInterface。このメンバーのメソッドは、外部構造体で呼び出し可能、またはオーバーライド可能です。
                    extend非抽象サブクラスを拡張するために?私にとって、これは、internalによって実装されている既存のメソッドを使用しながら、特定のメソッドのみをオーバーライドするための便利な方法Interfaceです。
                    return r.Interface.Less(j, i)、親実装を呼び出していますか?
                    sort.Sort(sort.Reverse(sort.IntSlice(example)))。私にとってここでの問題点は、Sortメソッドが逆構造体にプロモートされますが、呼び出しは非メンバー(レシーバー)スタイルです。
                    承諾した回答で理解できましたが、自分の考え方に合った説明を投稿することにしました。
「有効ゴー」が埋め込まれた他のインターフェースを有するインターフェースの例を有します。
// ReadWriter is the interface that combines the Reader and Writer interfaces.
type ReadWriter interface {
    Reader
    Writer
}
および他の構造体を埋め込んだ構造体:
// ReadWriter stores pointers to a Reader and a Writer.
// It implements io.ReadWriter.
type ReadWriter struct {
    *Reader  // *bufio.Reader
    *Writer  // *bufio.Writer
}
しかし、インターフェースを埋め込んだ構造体については言及されていません。私はこれをsortパッケージで見て混乱しました:
type Interface interface {
    Len() int
    Less(i, j int) bool
    Swap(i, j int)
}
...
type reverse struct {
    Interface
}
しかし、アイデアは単純です。それはほとんど同じです:
type reverse struct {
    IntSlice  // IntSlice struct attaches the methods of Interface to []int, sorting in increasing order
}
IntSliceに昇格する方法reverse。
この:
type reverse struct {
    Interface
}
つまり、sort.reverseインターフェイスを実装する構造体sort.Interfaceや、インターフェイスにあるメソッドを埋め込むことができ、それらはにプロモートされreverseます。
sort.InterfaceLess(i, j int) boolオーバーライドできるメソッドがあります:
// Less returns the opposite of the embedded implementation's Less method.
func (r reverse) Less(i, j int) bool {
    return r.Interface.Less(j, i)
}
理解の混乱
type reverse struct {
    Interface
}
構造体は常に固定構造、つまり固定タイプのフィールドの数が固定されていると思っていました。
しかし、以下は私が間違っていることを証明しています:
package main
import "fmt"
// some interface
type Stringer interface {
    String() string
}
// a struct that implements Stringer interface
type Struct1 struct {
    field1 string
}
func (s Struct1) String() string {
    return s.field1
}
// another struct that implements Stringer interface, but has a different set of fields
type Struct2 struct {
    field1 []string
    dummy bool
}
func (s Struct2) String() string {
    return fmt.Sprintf("%v, %v", s.field1, s.dummy)
}
// container that can embedd any struct which implements Stringer interface
type StringerContainer struct {
    Stringer
}
func main() {
    // the following prints: This is Struct1
    fmt.Println(StringerContainer{Struct1{"This is Struct1"}})
    // the following prints: [This is Struct1], true
    fmt.Println(StringerContainer{Struct2{[]string{"This", "is", "Struct1"}, true}})
    // the following does not compile:
    // cannot use "This is a type that does not implement Stringer" (type string)
    // as type Stringer in field value:
    // string does not implement Stringer (missing String method)
    fmt.Println(StringerContainer{"This is a type that does not implement Stringer"})
}
    声明
type reverse struct {
    Interface
}
reverseインターフェイスを実装するすべてのもので初期化できますInterface。例:
&reverse{sort.Intslice([]int{1,2,3})}
このように、エンベディッドInterfaceバリューによって実装されたすべてのメソッドはreverse、たとえばLess並べ替えを逆にするために、それらの一部をオーバーライドできる間、外部に入力されます。
これは、を使用しsort.Reverseたときに実際に発生することです。埋め込みについては、仕様の構造体セクションで読むことができます。
sort.Sort(sort.Reverse(sort.IntSlice(example)))。私にとってここでの問題点は、Sortメソッドが逆構造体にプロモートされますが、呼び出しは非メンバー(レシーバー)スタイルです。
                    Sortメソッドはプロモートされません。満足するものが必要でsort.Interfaceあり、リバースはそのようなものです。埋め込まれたsort.Interfaceデータの関連するメソッドを変更するだけで、結果のソートがリバースされます。
                    私も説明します。sortパッケージは、アンエクスポートタイプ定義reverse構造体であり、その埋め込み動画をInterface。
type reverse struct {
    // This embedded Interface permits Reverse to use the methods of
    // another Interface implementation.
    Interface
}
これにより、Reverseは別のインターフェイス実装のメソッドを使用できます。これはいわゆるcomposition、Goの強力な機能です。
のLessメソッドは、エンベディッド値のメソッドをreverse呼び出しますが、インデックスが反転しているため、並べ替え結果の順序が逆になります。LessInterface
// Less returns the opposite of the embedded implementation's Less method.
func (r reverse) Less(i, j int) bool {
    return r.Interface.Less(j, i)
}
Lenそして、Swapの他の2つの方法はreverse、暗黙のうちに元によって提供されInterface、それが埋め込まれたフィールドであるため、値。エクスポートされたReverse関数reverseは、元のInterface値を含むタイプのインスタンスを返します。
// Reverse returns the reverse order for data.
func Reverse(data Interface) Interface {
    return &reverse{data}
}
    Lessメソッドは、エンベディッドバリューのメソッドをreverse呼び出しますが、インデックスが反転しているため、並べ替え結果の順序が逆になります。」-これは親実装の呼び出しのように見えます。LessInterface
                    この機能は、テストでモックを作成するときに非常に役立ちます。
これがそのような例です:
package main_test
import (
    "fmt"
    "testing"
)
// Item represents the entity retrieved from the store
// It's not relevant in this example
type Item struct {
    First, Last string
}
// Store abstracts the DB store
type Store interface {
    Create(string, string) (*Item, error)
    GetByID(string) (*Item, error)
    Update(*Item) error
    HealthCheck() error
    Close() error
}
// this is a mock implementing Store interface
type storeMock struct {
    Store
    // healthy is false by default
    healthy bool
}
// HealthCheck is mocked function
func (s *storeMock) HealthCheck() error {
    if !s.healthy {
        return fmt.Errorf("mock error")
    }
    return nil
}
// IsHealthy is the tested function
func IsHealthy(s Store) bool {
    return s.HealthCheck() == nil
}
func TestIsHealthy(t *testing.T) {
    mock := &storeMock{}
    if IsHealthy(mock) {
        t.Errorf("IsHealthy should return false")
    }
    mock = &storeMock{healthy: true}
    if !IsHealthy(mock) {
        t.Errorf("IsHealthy should return true")
    }
}
使用することによって:
type storeMock struct {
    Store
    ...
}
すべてをあざける必要はありません Storeメソッド。HealthCheckこの方法のみがTestIsHealthyテストで使用されるため、モックのみが可能です。
結果の下に testコマンド下:
$ go test -run '^TestIsHealthy$' ./main_test.go           
ok      command-line-arguments  0.003s
現実の世界の例テストするときに1を見つけることができます。このユースケースのAWS SDKを。
それをさらに明確にするために、ここに醜い代替案があります-Storeインターフェースを満たすために実装する必要がある最小のもの:
type storeMock struct {
    healthy bool
}
func (s *storeMock) Create(a, b string) (i *Item, err error) {
    return
}
func (s *storeMock) GetByID(a string) (i *Item, err error) {
    return
}
func (s *storeMock) Update(i *Item) (err error) {
    return
}
// HealthCheck is mocked function
func (s *storeMock) HealthCheck() error {
    if !s.healthy {
        return fmt.Errorf("mock error")
    }
    return nil
}
func (s *storeMock) Close() (err error) {
    return
}