ChaChaPoly
ChaChaPoly

Reputation: 1851

Go memory address changing

I am very new to go, so please bear with me here. I am trying to interact with my QNAP NAS through go. So far I can log in, but not back out. It seems like the memory address of qnap changes:

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()

}

This code prints the following:

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

I am not sure why the address changes right before the Logout method.

I get the following error:

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

Upvotes: 0

Views: 1485

Answers (1)

Adrian
Adrian

Reputation: 46592

& gives you the address of a variable. &q in your Logout function gives you the address of q, which is a local variable. The value of that local variable is, in turn, an address, because q is itself a pointer (to a struct of type QNAP). The memory address that's printed being different is a red herring; your nil pointer dereference is the real issue. If you want the same address, you would print the value of q, not &q; and in main() you would likewise print the value of qnap, not &qnap, for the same reason.

Here's an example that might make things clearer: https://play.golang.org/p/pDpL0-GYuM

Upvotes: 3

Related Questions