如何将结构作为参数传递给函数

Nag*_*gri -1 json struct types go slice

我怎么能做这样的事情?

我试图将 astruct作为参数传递给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)
}
Run Code Online (Sandbox Code Playgroud)

正如您在代码中看到的,我试图将 的前 100 个元素发送entityProperties.Entities structsendData. 我知道这在语法上是错误的。

icz*_*cza 12

只需在函数之外声明您的类型:

type entity struct {
    Id         string            `json:"id"`
    Properties map[string]string `json:"properties"`
    Type       string            `json:"type"`
}
Run Code Online (Sandbox Code Playgroud)

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)
}
Run Code Online (Sandbox Code Playgroud)

另请注意,不能保证客户端将发送至少 100 个实体,因此您应该检查切片表达式是否可能导致运行时恐慌:

max := 100
if len(entityProperties.Entities) < max {
    max = len(entityProperties.Entities)
}
sendData(entityProperties.Entities[:max])
Run Code Online (Sandbox Code Playgroud)

此外,检查无效的 JSON 是不必要的:如果 JSON 无效,json.Unmarshal()将报告(非nil)错误,您会知道的。

更进一步,您甚至不必将完整的主体读入内存(读入一个字节片),您可以json.Decoder像这样直接从它读取(没有中间内存缓冲区):

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

而最后的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])
}
Run Code Online (Sandbox Code Playgroud)