简体   繁体   English

通过引用在结构中设置字段

[英]Set field in struct by reference

I want to set the Request struct field Response by reference in the function request in order to use it further below in the main function.我想在函数request中通过引用设置Request结构字段Response ,以便在主函数的下面进一步使用它。 Unfortunately, I get the following error:不幸的是,我收到以下错误:

{Status: StatusCode:0 Proto: ProtoMajor:0 ProtoMinor:0 Header:map[] Body:<nil> ContentLength:0 TransferEncoding:[] Close:false Uncompressed:false Trailer:map[] Request:<nil> TLS:<nil>}
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x18 pc=0x4922d1]

goroutine 1 [running]:
io.copyBuffer(0x72dbc0, 0xc0000a8008, 0x0, 0x0, 0xc000196000, 0x8000, 0x8000, 0xb9, 0x0, 0x0)
    /usr/lib/go/src/io/io.go:402 +0x101
io.Copy(...)
    /usr/lib/go/src/io/io.go:364
main.main()
    /home/y/code/scmc/foo.go:49 +0x20d
exit status 2

The code looks as follows:代码如下所示:

package main

import (
    "fmt"
    "io"
    "net/http"
    "os"
)

type Request struct {
    Method   string
    Url      string
    Reader   io.Reader
    Response *http.Response
}

func request(r Request) error {
    request, err := http.NewRequest(r.Method, r.Url, r.Reader)
    if err != nil {
        return err
    }

    client := &http.Client{}
    response, err := client.Do(request)
    if err != nil {
        return err
    }

    if r.Response != nil {
        r.Response = response
    }

    return nil
}

func main() {
    var r http.Response

    if err := request(Request{
        Method:   "GET",
        Url:      "http://google.com",
        Response: &r,
    }); err != nil {
        panic(err)
    }

    fmt.Printf("%+v\n", r)

    if _, err := io.Copy(os.Stdout, r.Body); err != nil {
        panic(err)
    }
}

What am I doing wrong?我究竟做错了什么?

client.Do() returns a pointer: *http.Response . client.Do()返回一个指针: *http.Response If you want to "transfer" a *http.Response pointer value out of your function, you need a pointer value to this type which you may set.如果你想从你的函数中“传输”一个*http.Response指针值,你需要一个指向你可以设置的类型的指针值。 That pointer value has to be of type **http.Response (note: pointer to pointer):该指针值必须是**http.Response类型(注意:指向指针的指针):

type Request struct {
    Method   string
    Url      string
    Reader   io.Reader
    Response **http.Response
}

Inside your request() function you need to set the pointed value:request()函数中,您需要设置指向的值:

if r.Response != nil {
    *r.Response = response
}

And when calling request() :当调用request()

var r *http.Response

if err := request(Request{
    Method:   "GET",
    Url:      "http://google.com",
    Response: &r,
}); err != nil {
    panic(err)
}

For analogy:打个比方:

If you'd want to transfer out an int value:如果您想转出一个int值:

func do(i *int) {
    *i= 10
}

// Calling it:
var i int
do(&i)

To transfer out an *int value:要传出*int值:

func do(i **int) {
    x := 10
    *i = &x
}

// Calling it:
var i *int
do(&i)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM