Скрытые методы в реализации типов? - PullRequest
0 голосов
/ 18 июня 2019

Просматривая некоторые источники в net/http и связанных библиотеках, я обнаружил что-то , что вызвало у меня любопытство.Я смотрю на версию 1.12 здесь.

func (p *ReverseProxy) handleUpgradeResponse(rw http.ResponseWriter, req *http.Request, res *http.Response) {
  ...
  hj, ok := rw.(http.Hijacker)
  ...
  conn, brw, err := hj.Hijack()
  ...
}

Я видел подобные вещи в других местах, а также за пределами стандартной библиотеки.Что здесь происходит?Некоторые методы реализации интерфейса скрыты до тех пор, пока не произойдет конкретное утверждение?Почему я не могу просто позвонить Hijack() на объект rw?

1 Ответ

0 голосов
/ 18 июня 2019

Методы кажутся скрытыми, потому что функция принимает тип интерфейса.Интерфейс http.ResponseWriter не определяет метод Hijack().Это определено в интерфейсе http.Hijacker.Конкретный тип может реализовывать несколько интерфейсов.Но даже если такой конкретный тип передается в область, где его определение типа является интерфейсом, дополнительные методы не будут доступны.Таким образом, в сомнительном примере утверждение типа выполняется, чтобы сделать метод Hijack() доступным.

Некоторые примеры ( детская площадка ):

package main

import (
    "fmt"
)

type Ship interface {
    Load(containers []string)
    Condition() []string
}

type Sea interface {
    Draft() int
}

// seaShip implements the Sea and Ship interfaces
type seaShip struct {
    containers []string
}

// Load is only part of the Ship interface
func (ss *seaShip) Load(containers []string) {
    ss.containers = append(ss.containers, containers...)
}

// Condition is only part of the Ship interface
func (ss *seaShip) Condition() []string {
    return ss.containers
}

// Draft is only part of the Sea interface
func (ss *seaShip) Draft() int {
    return len(ss.containers)
}

// Pirates is not defined in any interface and therefore can only be called on the concrete type
func (ss *seaShip) Pirates() string {
    return "Help!"
}

// NewShip returns an implementation of the Ship interface
func NewShip() Ship {
    return &seaShip{}
}

func main() {
    ship := NewShip()
    ship.Load([]string{"Beer", "Wine", "Peanuts"})
    fmt.Println(ship.Condition())
    // Won't compile, method is not part of interface!
    // fmt.Println(ship.Draft())

    // Assert to make Draft() available
    sea := ship.(Sea)
    fmt.Println(sea.Draft())

    // Won't compile, methods are not part of interface!
    // fmt.Println(sea.Condition())
    // fmt.Println(sea.Pirates())

    // Assert to the concrete type makes all methods available
    ss := sea.(*seaShip)
    fmt.Println(ss.Condition())
    fmt.Println(ss.Pirates())
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...