去内存地址改变

时间:2017-05-23 14:02:28

标签: pointers go

我很新,所以请在这里忍受我。我试图通过去与我的QNAP NAS进行互动。到目前为止,我可以登录,但不能退出。似乎qnap的内存地址发生了变化:

package main

import (
    "net/url"
    "fmt"
    "net/http"
    "encoding/base64"
    "io/ioutil"
    "encoding/xml"
    "errors"
)

// QNAP REST API
type QNAPAPI struct {
    Login,
    Logout,
    SysReq,
    MiscAct,
    MyCloud string
}

// QNAP NAS info
type QNAP struct {
    URI, Username, Password, SID string
    Client *http.Client
    API QNAPAPI
}

// Assign API endpoints to struct
func initializeQNAPApi(API *QNAPAPI) QNAPAPI {
    API.Login = "/cgi-bin/authLogin.cgi"
    API.Logout = "/cgi-bin/authLogout.cgi"
    API.SysReq = "/cgi-bin/sys/sysRequest.cgi"
    API.MiscAct = "/cgi-bin/misc/misc_action.cgi"
    API.MyCloud = "/cgi-bin/my_cloud/cloudRequest.cgi"
    return *API
}

// Login to NAS
func (q *QNAP) Login() (string, error) {
    // Match fields in XML
    type LoginResponse struct {
        AuthPassed int `xml:"authPassed"`
        SID        string `xml:"authSid"`
    }
    // Create data structure to bind XML to
    loginResponse := LoginResponse{}

    // Prepare POST headers
    postData := url.Values{
        "user": {q.Username},
        "serviceKey": {"1"},
        "pwd": {base64.StdEncoding.EncodeToString([]byte(q.Password))},
    }

    res, err := q.Client.PostForm(q.URI + q.API.Login, postData)
    if err != nil {
        return "", err
    }
    defer res.Body.Close()

    responseData, err := ioutil.ReadAll(res.Body)
    if err != nil {
        return "", err
    }

    xml.Unmarshal(responseData, &loginResponse)
    if loginResponse.AuthPassed == 1 {
        q.SID = loginResponse.SID
        return loginResponse.SID, nil
    }
    return "", errors.New("Unable to login!")
}

// Logout from NAS
func (q *QNAP) Logout() (string, error) {
    fmt.Println(&q)
    postData := url.Values{
        "logout": {"1"},
        "sid": {q.SID},
    }

    // PROBLEM HERE???
    res, err := q.Client.PostForm(q.URI + q.API.Logout, postData)
    defer res.Body.Close()


    fmt.Println(err)
    fmt.Println(res)
    responseData, err := ioutil.ReadAll(res.Body)
    fmt.Println(err)
    fmt.Println(string(responseData))
    return "x", nil
}



func main() {
    httpClient := &http.Client{}

    qnap := &QNAP{
        URI: "http://redacted.myqnapcloud.com:8080",
        Username: "MyUserName",
        Password: "MyPassword",
        Client: httpClient,
        API: initializeQNAPApi(&QNAPAPI{}),
    }
    fmt.Println(&qnap)
    sid, err := qnap.Login()
    if err != nil {
        fmt.Println(err)
    }
    fmt.Printf("Logged in with SID: %s\n", sid)
    // MEMORY ADDRESS CHANGES - WHY???
    fmt.Println(&qnap)
    qnap.Logout()

}

此代码打印以下内容:

0xc042060020
Logged in with SID: jli2wt7t
0xc042060020
0xc042004028

我不确定为什么地址会在Logout方法之前发生变化。

我收到以下错误:

panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x0 addr=0x40 pc=0x5ed063]

goroutine 1 [running]:
main.(*QNAP).Logout(0xc04204a780, 0x0, 0x0, 0x0, 0x0)
    C:/Users/redacted/test.go:85 +0x303
main.main()
    C:/Users/redacted/test.go:115 +0x44e
exit status 2

1 个答案:

答案 0 :(得分:1)

&为您提供变量的地址。 &q函数中的Logout会为您提供q的地址,这是一个局部变量。该局部变量的又是一个地址,因为q本身就是一个指针(对于QNAP类型的结构)。打印的内存地址不同是红鲱鱼;你的nil指针取消引用是真正的问题。如果您想要相同的地址,则打印q的值,而不是&q;在main()中,出于同样的原因,您同样会打印qnap的值,而不是&qnap

以下是一个可能使事情更清晰的例子:https://play.golang.org/p/pDpL0-GYuM