【问题标题】:nil point deference in golang using govmomi library使用 govmomi 库在 golang 中的零点尊重
【发布时间】:2019-03-28 06:43:57
【问题描述】:

我正在尝试使用 govmomi 库 (https://github.com/vmware/govmomi) 对 VM 进行一些自动更改,但过去几个小时我似乎无法解决第 134 行和第 136 行的 nil 指针异常。我曾经让它工作,但我不确定我现在做错了什么,因为我尝试了很多组合,但现在似乎没有任何工作......

package main

import (
    "context"
    "flag"
    "github.com/vmware/govmomi"
    "github.com/vmware/govmomi/vim25"
    "github.com/vmware/govmomi/vim25/soap"
    "net/url"
    "os"
    "strings"

    "fmt"

    "github.com/vmware/govmomi/govc/flags"

    "github.com/vmware/govmomi/vim25/types"
    "log"
)


type change struct {
    *flags.VirtualMachineFlag
}

const (
    envURL      = "GOVC_URL"
    envUserName = "GOVC_USERNAME"
    envPassword = "GOVC_PASSWORD"
    envInsecure = "GOVC_INSECURE"
)

// getEnvString returns string from environment variable.
func getEnvString(v string, def string) string {
    r := os.Getenv(v)
    if r == "" {
        return def
    }

    return r
}

// getEnvBool returns boolean from environment variable.
func getEnvBool(v string, def bool) bool {
    r := os.Getenv(v)
    if r == "" {
        return def
    }

    switch strings.ToLower(r[0:1]) {
    case "t", "y", "1":
        return true
    }

    return false
}

var urlDescription = fmt.Sprintf("ESX or vCenter URL [%s]", envURL)
var urlFlag = flag.String("url", getEnvString(envURL, "https://username:password@host"+vim25.Path), urlDescription)

var insecureDescription = fmt.Sprintf("Don't verify the server's certificate chain [%s]", envInsecure)
var insecureFlag = flag.Bool("insecure", getEnvBool(envInsecure, false), insecureDescription)

func processOverride(u *url.URL) {
    envUsername := os.Getenv(envUserName)
    envPassword := os.Getenv(envPassword)

    // Override username if provided
    if envUsername != "" {
        var password string
        var ok bool

        if u.User != nil {
            password, ok = u.User.Password()
        }

        if ok {
            u.User = url.UserPassword(envUsername, password)
        } else {
            u.User = url.User(envUsername)
        }
    }

    // Override password if provided
    if envPassword != "" {
        var username string

        if u.User != nil {
            username = u.User.Username()
        }

        u.User = url.UserPassword(username, envPassword)
    }
}

func NewClient(ctx context.Context) (*govmomi.Client, error) {
    flag.Parse()

    // Parse URL from string
    u, err := soap.ParseURL(*urlFlag)
    if err != nil {
        return nil, err
    }

    // Override username and/or password as required
    processOverride(u)

    // Connect and log in to ESX or vCenter
    return govmomi.NewClient(ctx, u, *insecureFlag)
}

func main() {

    ctx := context.Background()

    // Connect and login to ESX or vCenter
    c, err := NewClient(ctx)
    if err != nil {
        log.Fatal(err)
    }

    defer c.Logout(ctx)

    var spec *types.VirtualMachineConfigSpec

    var cmd *change

    var flip bool

    flip = false

    spec.VPMCEnabled = &flip

    vm, err := cmd.VirtualMachine()

    task, err := vm.Reconfigure(ctx, *spec)
    if err != nil {
        println(err)
    }

    fmt.Println(task.Wait(ctx))
}

引发错误的 2 行是:

spec.VPMCEnabled = &flip

vm, err := cmd.VirtualMachine()

两者似乎都抛出相同的panic: runtime error: invalid memory address or nil pointer dereference。如果我注释掉第一个抛出错误,那么第二个抛出它。

我认为两者无关,但我不太清楚如何正确地进行取消引用。

----更新编辑1--------------

我通过以下响应对此进行了一些更改,但仍然无法解决task, err := vm.Reconfigure(ctx, *spec) 上的错误...

package main

import (
    "context"
    "flag"
    "github.com/vmware/govmomi"
    "github.com/vmware/govmomi/object"
    "github.com/vmware/govmomi/vim25"
    "github.com/vmware/govmomi/vim25/soap"
    "net/url"
    "os"
    "strings"

    "fmt"

    "github.com/vmware/govmomi/vim25/types"
    "log"
)


const (
    envURL      = "GOVC_URL"
    envUserName = "GOVC_USERNAME"
    envPassword = "GOVC_PASSWORD"
    envInsecure = "GOVC_INSECURE"
)

// getEnvString returns string from environment variable.
func getEnvString(v string, def string) string {
    r := os.Getenv(v)
    if r == "" {
        return def
    }

    return r
}

// getEnvBool returns boolean from environment variable.
func getEnvBool(v string, def bool) bool {
    r := os.Getenv(v)
    if r == "" {
        return def
    }

    switch strings.ToLower(r[0:1]) {
    case "t", "y", "1":
        return true
    }

    return false
}

var urlDescription = fmt.Sprintf("ESX or vCenter URL [%s]", envURL)
var urlFlag = flag.String("url", getEnvString(envURL, "https://username:password@host"+vim25.Path), urlDescription)

var insecureDescription = fmt.Sprintf("Don't verify the server's certificate chain [%s]", envInsecure)
var insecureFlag = flag.Bool("insecure", getEnvBool(envInsecure, false), insecureDescription)

func processOverride(u *url.URL) {
    envUsername := os.Getenv(envUserName)
    envPassword := os.Getenv(envPassword)

    // Override username if provided
    if envUsername != "" {
        var password string
        var ok bool

        if u.User != nil {
            password, ok = u.User.Password()
        }

        if ok {
            u.User = url.UserPassword(envUsername, password)
        } else {
            u.User = url.User(envUsername)
        }
    }

    // Override password if provided
    if envPassword != "" {
        var username string

        if u.User != nil {
            username = u.User.Username()
        }

        u.User = url.UserPassword(username, envPassword)
    }
}

func NewClient(ctx context.Context) (*govmomi.Client, error) {
    flag.Parse()

    // Parse URL from string
    u, err := soap.ParseURL(*urlFlag)
    if err != nil {
        return nil, err
    }

    // Override username and/or password as required
    processOverride(u)

    // Connect and log in to ESX or vCenter
    return govmomi.NewClient(ctx, u, *insecureFlag)
}

func main() {

    ctx := context.Background()

    // Connect and login to ESX or vCenter
    c, err := NewClient(ctx)
    if err != nil {
        log.Fatal(err)
    }

    defer c.Logout(ctx)

    var spec *types.VirtualMachineConfigSpec
    spec = new(types.VirtualMachineConfigSpec)


    var flip bool

    flip = false

    spec.VPMCEnabled = &flip

    var vm *object.VirtualMachine
    vm = new(object.VirtualMachine)


    task, err := vm.Reconfigure(ctx, *spec)
    if err != nil {
        println(err)
    }

    fmt.Println(task.Wait(ctx))

}

我得到的完整错误是:

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x280 pc=0x14e18f6]

goroutine 1 [running]:
github.com/vmware/govmomi/vim25.(*Client).RoundTrip(0x0, 0x1886f00, 0xc000016088, 0x1884140, 0xc000298720, 0x1884140, 0xc000298740, 0x300, 0x16e8ac0)
        /Users/ronakpatel/go/src/github.com/vmware/govmomi/vim25/client.go:89 +0x26
github.com/vmware/govmomi/vim25/methods.ReconfigVM_Task(0x1886f00, 0xc000016088, 0x1884060, 0x0, 0xc0002d0000, 0xc000288000, 0xc000080400, 0x0)
        /Users/ronakpatel/go/src/github.com/vmware/govmomi/vim25/methods/methods.go:10879 +0xb8
github.com/vmware/govmomi/object.VirtualMachine.Reconfigure(0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1886f00, 0xc000016088, 0x0, ...)
        /Users/ronakpatel/go/src/github.com/vmware/govmomi/object/virtual_machine.go:207 +0x19b
main.main()
        /Users/ronakpatel/go/src/awesomeProject1/main.go:143 +0x1ec
exit status 2

----更新编辑2----------

我改变了一些东西并使用了下面提供的答案,但现在我再次收到错误但在这一部分:task, err := vm.Reconfigure(ctx, spec1)

错误:

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x153d05a]

goroutine 1 [running]:
main.main()
        /Users/ronakpatel/go/src/awesomeProject1/main.go:134 +0x19a
exit status 2

代码:

spec1 := types.VirtualMachineConfigSpec{
    VPMCEnabled: &[]bool{false}[0],
}

var vm *object.VirtualMachine

var vmf *flags.VirtualMachineFlag

vmf, ctx = flags.NewVirtualMachineFlag(ctx)

vm, _ = vmf.VirtualMachine()

task, err := vm.Reconfigure(ctx, spec1)
if err != nil {
    println(err)
}

fmt.Println(task.Wait(ctx))

【问题讨论】:

  • vm, err := cmd.VirtualMachine() 使用vm前检查错误。
  • 虽然点异常的原因并没有那么远......
  • 那么它会到达哪里呢?当我突出显示的行在给定示例代码中的 133 上时说“134 和 136”(缺少包语句的 +1 行)没有帮助。如果您需要准确的帮助,请提供准确的信息。
  • 您还应该提供您遇到的错误的相关部分
  • 啊没看到...只是对其进行了编辑以在行上更正它...它停在 134 并且当我将其注释掉时...它停在136....都有这些错误:panic: runtime error: invalid memory address or nil pointer dereference

标签: go govmomi


【解决方案1】:
    var spec *types.VirtualMachineConfigSpec // error: spec is nil pointer
    spec = new(types.VirtualMachineConfigSpec) // fix: spec is not nil

    var cmd *change

    var flip bool

    flip = false

    // used here
    spec.VPMCEnabled = &flip

    vm, err := cmd.VirtualMachine()

【讨论】:

  • 谢谢!离我更近了,但这部分仍然抛出同样的错误:vm, err := cmd.VirtualMachine()
  • @lightweight 当你声明一个指针变量时,如果没有初始化它,它将为零,在这样的变量上调用方法几乎总是会给你那个错误。无论您在代码中使用什么,只要确保它已初始化即可。
  • @lightweight 好的,*change 中的 *flags.VirtualMachineFlag 仍然是 nil 指针
  • @lightweight godoc.org/github.com/vmware/govmomi/govc/… 你可以声明*flags.VirtualMachineFlag 关注文档
  • 啊,谢谢!所以我做了你所说的一些改变并清理了一些东西(我认为),但现在我现在遇到了同样的错误task, err := vm.Reconfigure(ctx, spec1) :-( ....另外,感谢您的耐心....
猜你喜欢
  • 2017-11-02
  • 2015-07-22
  • 2015-05-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-24
  • 1970-01-01
相关资源
最近更新 更多