2016-10-02 5 views
0

Я пытаюсь понять код, используемый в моей компании. Я новичок в лангах, и я уже прошел учебник на своем официальном сайте. Тем не менее, я с трудом переношу голову вокруг пустых интерфейсов, то есть интерфейса {}. Из различных источников в Интернете я понял, что пустой интерфейс может содержать любой тип. Но мне сложно определить код, особенно некоторые из функций. Я не буду публиковать здесь все, но только минимальные функции, в которых он был использован. Пожалуйста, несите меня!Использование пустых интерфейсов в go

Function (I am trying to understand): 

func (this *RequestHandler) CreateAppHandler(rw http.ResponseWriter, r *http.Request) *foo.ResponseError { 
    var data *views.Data = &views.Data{Attributes: &domain.Application{}} 
    var request *views.Request = &views.Request{Data: data} 


    if err := json.NewDecoder(r.Body).Decode(request); err != nil { 
     logrus.Error(err) 
     return foo.NewResponsePropogateError(foo.STATUS_400, err) 
    } 
    requestApp := request.Data.Attributes.(*domain.Application) 
    requestApp.CreatedBy = user 

Установка некоторый контекст, RequestHandler это структура определяется в том же пакете, этот код. domain и views являются отдельными пакетами. Приложение представляет собой структуру в домене пакета. Следующие две структуры являются частью взглядов пакета:

type Data struct { 
    Id   string  `json:"id"` 
    Type  string  `json:"type"` 
    Attributes interface{} `json:"attributes"` 
} 

type Request struct { 
    Data *Data `json:"data"` 
} 

Следующая являются частью пакета JSON:

func NewDecoder(r io.Reader) *Decoder { 
    return &Decoder{r: r} 
} 

func (dec *Decoder) Decode(v interface{}) error { 
    if dec.err != nil { 
     return dec.err 
    } 

    if err := dec.tokenPrepareForDecode(); err != nil { 
     return err 
    } 

    if !dec.tokenValueAllowed() { 
     return &SyntaxError{msg: "not at beginning of value"} 
    } 

    // Read whole value into buffer. 
    n, err := dec.readValue() 
    if err != nil { 
     return err 
    } 
    dec.d.init(dec.buf[dec.scanp : dec.scanp+n]) 
    dec.scanp += n 

    // Don't save err from unmarshal into dec.err: 
    // the connection is still usable since we read a complete JSON 
    // object from it before the error happened. 
    err = dec.d.unmarshal(v) 

    // fixup token streaming state 
    dec.tokenValueEnd() 

    return err 
} 


type Decoder struct { 
    r  io.Reader 
    buf []byte 
    d  decodeState 
    scanp int // start of unread data in buf 
    scan scanner 
    err error 

    tokenState int 
    tokenStack []int 
} 

Теперь я понял, что в STRUCT данных в представлениях пакетов, Приложение будучи установленным как тип для пустого интерфейса. После этого создается указатель на запрос в том же пакете, который указывает на данные переменной.

У меня есть следующие сомнения:

  1. Что именно this ключевое слово означает в Go? Какова цель написания this * RequestHandler?
  2. Инициализация структуры в Go может быть выполнена при присвоении ей переменной путем указания значений всех ее членов. Однако здесь для структуры Data назначено только пустое значение интерфейса, а значения для двух других полей не назначены?
  3. В чем преимущество назначения структуры приложения пустующему интерфейсу? Означает ли это, что я могу использовать элементы структуры напрямую с помощью интерфейсной переменной?
  4. Может ли кто-нибудь помочь мне разобраться в значении этого утверждения? json.NewDecoder(r.Body).Decode(request)?

Хотя я знаю, что это слишком много, но мне сложно определить значение интерфейсов в Go. Пожалуйста помоги!

ответ

1
  1. this не является ключевым словом в go; там может быть использовано любое имя переменной. Это называется приемником . Функция, объявленная таким образом, должна быть вызвана как thing.func(params), где «вещь» является выражением типа получателя. Внутри функции приемник установлен в значение thing.

  2. Строковый литерал не должен содержать значений для всех полей (или любого из них). Любые поля, не заданные явно, будут иметь нулевое значение для их типов.

  3. Как вы сказали, пустой интерфейс может принимать значение любого типа.Для того, чтобы использовать значение типа interface{}, вы бы использовать утверждение типа или переключатель в типа для определения типа значения, или вы могли бы использовать отражение использовать значение без необходимости иметь код для конкретного типа.

  4. Что конкретно об этом заявлении вы не понимаете? json - это имя пакета, в котором объявлена ​​функция NewDecoder. Эта функция вызывается, а затем возвращается значение Decode (которое реализуется типом возвращаемого значения NewDecoder).

Вы можете посмотреть на Effective Go и/или The Go Programming Language Specification для получения дополнительной информации.