Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Golang update pass by reference value

I am calling a function to do a http request, two pass by reference parameter is used for the function. I pass the []byte to v interface. I want the function to update the v interface reference value. The response body is a string, I want to pass the string value to v interface. However, tried many ways but not success.

Here is the code, you can see I declare byts as v.(*[]byte) in order to make v updated with the string value of response body. But it does not work. The v is always nil. Please suggest any way to make v can be updated with the string value.

func (s *BackendConfiguration) Do(req *http.Request, v interface{}) error {
    res, err := s.HTTPClient.Do(req)
    defer res.Body.Close()
    resBody, err := ioutil.ReadAll(res.Body)

    if v != nil {   
            byts, ok := v.(*[]byte)
            if len(resBody) > 0 {           
                byts = append(byts, resBody...)
                return nil
            }
        }
    }

    return nil
}
like image 709
want_to_be_calm Avatar asked Feb 20 '15 10:02

want_to_be_calm


1 Answers

Well, the main reason this does not work is because you think of "call by reference", a concept completely unknown to Go. Absolutely everything is called by value in Go and once you spell out what is a byte slice, a pointer to a byte slice, a pointer to byte slice wrapped inside an interface, a copy of the pointer to a byte slice extracted from the interface, and so on you'll see how to update the value the pointer to byte slice points to:

package main
import "fmt"
func f(v interface{}) {
    pbs := v.(*[]byte)
    *pbs = append(*pbs, []byte{9,8,7}...)
}
func main() {
    bs := []byte{1,2,3}
    pbs := &bs
    var v interface{} = pbs
    f(v)
    fmt.Printf("%v\n", *pbs)
}
like image 105
Volker Avatar answered Nov 15 '22 09:11

Volker