Семантика - Передача значения типа внешнего интерфейса во внутреннюю переменную интерфейса - PullRequest
0 голосов
/ 18 апреля 2020

Ниже приведен код прототипа для трехслойного API (с некоторыми ограничениями проектирования):

// Sample program demonstrating interface composition.
package main

import (
    "errors"
    "fmt"
    "io"
    "math/rand"
    "time"
)

func init() {
    rand.Seed(time.Now().UnixNano())
}

// =============================================================================

// Data is the structure of the data we are copying.
type Data struct {
    Line string
}

// =============================================================================

// Puller declares behavior for pulling data.
type Puller interface {
    Pull(d *Data) error
}

// Storer declares behavior for storing data.
type Storer interface {
    Store(d *Data) error
}

// PullStorer declares behavior for both pulling and storing.
type PullStorer interface {
    Puller
    Storer
}

// =============================================================================

// Xenia is a system we need to pull data from.
type Xenia struct {
    Host    string
    Timeout time.Duration
}

// Pull knows how to pull data out of Xenia.
func (*Xenia) Pull(d *Data) error {
    switch rand.Intn(10) {
    case 1, 9:
        return io.EOF

    case 5:
        return errors.New("Error reading data from Xenia")

    default:
        d.Line = "Data"
        fmt.Println("In:", d.Line)
        return nil
    }
}

// Pillar is a system we need to store data into.
type Pillar struct {
    Host    string
    Timeout time.Duration
}

// Store knows how to store data into Pillar.
func (*Pillar) Store(d *Data) error {
    fmt.Println("Out:", d.Line)
    return nil
}

// =============================================================================

// System wraps Xenia and Pillar together into a single system.
type System struct {
    Xenia
    Pillar
}

// =============================================================================

// pull knows how to pull bulks of data from any Puller.
func pull(p Puller, data []Data) (int, error) {
    for i := range data {
        if err := p.Pull(&data[i]); err != nil {
            return i, err
        }
    }

    return len(data), nil
}

// store knows how to store bulks of data from any Storer.
func store(s Storer, data []Data) (int, error) {
    for i := range data {
        if err := s.Store(&data[i]); err != nil {
            return i, err
        }
    }

    return len(data), nil
}

// Copy knows how to pull and store data from any System.
func Copy(ps PullStorer, batch int) error {
    data := make([]Data, batch)

    for {
        i, err := pull(ps, data)
        if i > 0 {
            if _, err := store(ps, data[:i]); err != nil {
                return err
            }
        }

        if err != nil {
            return err
        }
    }
}

// =============================================================================

func main() {
    sys := System{
        Xenia: Xenia{
            Host:    "localhost:8000",
            Timeout: time.Second,
        },
        Pillar: Pillar{
            Host:    "localhost:9000",
            Timeout: time.Second,
        },
    }

    if err := Copy(&sys, 3); err != io.EOF {
        fmt.Println(err)
    }
}

Насколько я понимаю,

Если вы передадите u, интерфейс содержит тип u и указатель на копию u. Если вы передадите &u, интерфейс будет содержать тип &u и адрес u.

Итак, ниже мое понимание переменных p, s & ps, из приведенного выше кода:

enter image description here

Но, я хотел бы подтвердить,

1) При pull(ps, data) делает первый элемент p содержит тип *System или Xenia тип, как первый элемент?

2) На store(ps, data[:i]), содержит ли первый элемент s тип *System или Pillar тип?

1 Ответ

1 голос
/ 18 апреля 2020

Тип: *System.

. Вы можете подтвердить это, добавив простое выражение для печати, например, fmt.Printf("%T\n", p)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...