Golang: 当将结构体传递给Go协程时,net/http客户端为空

huangapple go评论73阅读模式
英文:

Golang: net/http client nil when calling struct is passed to a go routine

问题

遇到了一个有趣的问题,即net/http(*Client)指针,特别是gcp go sdk compute.Operation包,尝试使用nil的http客户端发出请求,但只有在go例程中使用时才会出现此问题。这是一个示例:

import (
	compute "cloud.google.com/go/compute/apiv1"
	computepb "google.golang.org/genproto/googleapis/cloud/compute/v1"
)

func WaitForImages(op *compute.Operation, wg *sync.WaitGroup) {
    defer wg.Done()
    op.Wait(ctx)
    // 在创建完镜像后执行一些操作
}

func TakeImage(context context.Context, req *computepb.InsertImageRequest, wg *sync.WaitGroup) {
     c, err := compute.NewImagesRESTClient(ctx)
     defer c.Close()
     if err != nil {
         return
     }
     op, err := c.Insert(ctx, req)
     if err != nil {
         return
     }
     wg.Add(1)
     go WaitForImages(op, wg)
}

func Main() {
   images := [//图片列表]
   var wg *sync.WaitGroup = &sync.WaitGroup{}
   ctx := context.TODO()
   for _, img := range images {
        img := img
        req := &computepb.InsertImageRequest{

		    Project:  myProject,

		    ImageResource: &computepb.Image{
			    Name:       &img,
			    SourceDisk: &img,
		    },
	    }
        TakeImage(ctx, req, wg)
   }
   wg.Wait()
}

这是我得到的错误信息:

4  0x00000000006ee4d7 in net/http.(*Client).deadline
	     at /usr/lib/go-1.19beta1/src/net/http/client.go:188
	 5  0x00000000006f1105 in net/http.(*Client).do
	     at /usr/lib/go-1.19beta1/src/net/http/client.go:599
	 6  0x00000000006f0f4f in net/http.(*Client).Do
	     at /usr/lib/go-1.19beta1/src/net/http/client.go:581
	 7  0x00000000006f08a5 in net/http.(*Client).Get

只有在go例程中执行op.Wait(ctx)时才会出现此问题。如果我正常等待它,就不会出现问题。我的实际程序要长得多,我无法运行到程序的最后,实际上,如果我在调试器上点击"step"相对较慢,它在几行代码后就会发生panic,但在全速运行时,有时我可以发出2-3个镜像请求,有时只有1个。我尝试关闭golang垃圾收集器,以防它破坏了http客户端,但没有成功。

英文:

Having an interesting issue where the net/http(*Client) pointer, specifically the gcp go sdk compute.Operation package attempts to make a request with a nil http client but only when used in a go routine. Here is an example

import (
	compute "cloud.google.com/go/compute/apiv1"
	computepb "google.golang.org/genproto/googleapis/cloud/compute/v1"
)

func WaitForImages(op *compute.Operation, wg *sync.WaitGroup) {
    defer wg.Done()
    op.Wait(ctx)
    // Do some stuff after the image is made
}
func TakeImage(context context.Context, req *computepb.InsertImageRequest, wg *sync.WaitGroup) {
     c, err := compute.NewImagesRESTClient(ctx)
     defer c.Close()
     if err != nil {
         return
     }
     op, err := c.Insert(ctx, req)
     if err != nil {
         return
     }
     wg.Add(1)
     go WaitForImages(op, wg)
}

func Main() {
   images := [//List of images]
   var wg *sync.WaitGroup = &sync.WaitGroup{}
   ctx := context.TODO()
   for _, img := range images {
        img := img
        req := &computepb.InsertImageRequest{

		    Project:  myProject,

		    ImageResource: &computepb.Image{
			    Name:       &img,
			    SourceDisk: &img,
		    },
	    }
        TakeImage(ctx, req, wg)
   }
   wg.Wait()
}

This is the error I get

4  0x00000000006ee4d7 in net/http.(*Client).deadline
	     at /usr/lib/go-1.19beta1/src/net/http/client.go:188
	 5  0x00000000006f1105 in net/http.(*Client).do
	     at /usr/lib/go-1.19beta1/src/net/http/client.go:599
	 6  0x00000000006f0f4f in net/http.(*Client).Do
	     at /usr/lib/go-1.19beta1/src/net/http/client.go:581
	 7  0x00000000006f08a5 in net/http.(*Client).Get

This only happens if I do the op.Wait(ctx) inside a go routine. If I just wait for it regularly I get no issue. My actual program is much longer and I don't make it to the end of that program, in fact if I hit "step" on the debugger relatively slowly it panics after just a few lines, but in a full speed run sometimes I can make 2-3 image requests sometimes only 1. I tried turning off the golang garbage collector on the chance it was destroying the http client but had no luck.

答案1

得分: 1

问题出在c.Close()的调用上。尽管gcp返回一个新的compute.Operation客户端,但它仍然依赖于旧的compute.ImagesClient。在*compute.Operation.Wait()调用之前调用close会导致空指针解引用。

英文:

The issue was the c.Close() call. Even though gcp returns a new *compute.Operation client it is still reliant on the old *compute.ImagesClient. Calling close before the *compute.Operation.Wait() call causes a nil pointer dereference.

huangapple
  • 本文由 发表于 2022年10月13日 15:28:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/74051959.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定