Как передать struct в качестве параметра функции - PullRequest
0 голосов
/ 17 января 2020

Как я могу сделать что-то подобное?

Я пытаюсь передать struct в качестве параметра для работы в Go.

func handleEntityProperties(w http.ResponseWriter, r *http.Request) {
    const sliceSize = 100
    var entityProperties struct {
        Instance string `json:"instance"`
        Entities []struct {
            Id         string            `json:"id"`
            Properties map[string]string `json:"properties"`
            Type       string            `json:"type"`
        } `json:"entities"`
    }

    body, err := ioutil.ReadAll(r.Body)
    if err != nil {
        panic(err)
    }

    if !json.Valid([]byte(body)) {
        fmt.Fprintf(w, "invalid json")
        return
    }

    err = json.Unmarshal(body, &entityProperties)

    sendData(entityProperties.Entities[0:100])

    return
}

func sendData(entities struct) {
    log.Println("Doing things with entities ", entities)
}

, как вы можете видеть в код Я пытаюсь отправить первые 100 элементов entityProperties.Entities struct в sendData. Я знаю, что это синтаксически неправильно.

1 Ответ

12 голосов
/ 17 января 2020

Просто объявите свой тип вне функций:

type entity struct {
    Id         string            `json:"id"`
    Properties map[string]string `json:"properties"`
    Type       string            `json:"type"`
}

И повторно используйте его в handleEntityProperties() и в подписи sendData():

func handleEntityProperties(w http.ResponseWriter, r *http.Request) {
    const sliceSize = 100
    var entityProperties struct {
        Instance string   `json:"instance"`
        Entities []entity `json:"entities"`
    }

    body, err := ioutil.ReadAll(r.Body)
    if err != nil {
        panic(err)
    }

    if !json.Valid([]byte(body)) {
        fmt.Fprintf(w, "invalid json")
        return
    }

    err = json.Unmarshal(body, &entityProperties)

    sendData(entityProperties.Entities[0:sliceSize])

    return
}

func sendData(entities []entity) {
    log.Println("Doing things with entities ", entities)
}

Также обратите внимание, что есть нет никакой гарантии, что клиент отправит не менее 100 сущностей, поэтому вам следует убедиться, что в противном случае выражение среза может привести к пани времени выполнения c:

max := 100
if len(entityProperties.Entities) < max {
    max = len(entityProperties.Entities)
}
sendData(entityProperties.Entities[:max])

Также эта проверка на недопустимость JSON не нужно: если JSON недопустимо, json.Unmarshal() сообщит (не nil) об ошибке, и вы об этом узнаете.

Продвигаясь дальше, вы не будете даже если вам нужно прочитать полное тело в память (в байтовый фрагмент), вы можете использовать json.Decoder для непосредственного чтения из него (без промежуточного буфера памяти), например:

dec := json.NewDecoder(r.Body)
if err := dec.Decode(&entityProperties); err != nil {
    // handle error
}

И последнее утверждение return также не нужно.

Так что улучшенная версия может выглядеть так:

func handleEntityProperties(w http.ResponseWriter, r *http.Request) {
    var entityProperties struct {
        Instance string   `json:"instance"`
        Entities []entity `json:"entities"`
    }

    dec := json.NewDecoder(r.Body)
    if err := dec.Decode(&entityProperties); err != nil {
        // handle error
        http.Error(w, "invalid json", http.StatusBadRequest)
        return
    }

    max := 100
    if len(entityProperties.Entities) < max {
        max = len(entityProperties.Entities)
    }
    sendData(entityProperties.Entities[:max])
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...