无效操作 – 类型不匹配的字符串和nil

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

invalid operation - mismatched types string and nil

问题

我正在尝试创建一个连接到Google Cloud API的Go RESTful API。

出现了一个问题,描述如下:
invalid operation: req.ParentId != nil (类型不匹配,string和nil)

在创建本地API之前,我成功编写了一个Go模块,可以连接、认证并从Google Cloud中提取数据。现在我正在将该模块迁移到一个具有路径的Restful API。

该模块的目的是获取所有当前运行的虚拟机的列表。

以下是在将其更改为Restful API之前的模块(可以正常工作):

package main

import (
	"fmt"

	"example.com/compute"

	"bytes"
)

func main() {
	buf := new(bytes.Buffer)

	// 获取消息并打印
	r.HandleFunc("/virtualmachines", ListAllInstances)
	err := compute.ListAllInstances(buf, "unique-string-id")
	if err != nil {
		panic(err)
	}
	fmt.Println(buf.String()) // <======= 打印buf内容!
}


// 新文件:

package compute

// [START compute_instances_list_all]
import (
	"context"
	"fmt"
	"io"

	compute "cloud.google.com/go/compute/apiv1"
	"google.golang.org/api/iterator"
	computepb "google.golang.org/genproto/googleapis/cloud/compute/v1"
	"google.golang.org/protobuf/proto"
)

// listAllInstances打印项目中存在的所有实例,并按区域分组。
func ListAllInstances(w io.Writer, projectID string) error {
	// projectID := "your_project_id"
	ctx := context.Background()
	instancesClient, err := compute.NewInstancesRESTClient(ctx)


	if err != nil {
		return fmt.Errorf("NewInstancesRESTClient: %v", err)
	}
	defer instancesClient.Close()

	// 使用`MaxResults`参数限制API每个响应页面返回的结果数。
	req := &computepb.AggregatedListInstancesRequest{
		Project:    projectID,
		MaxResults: proto.Uint32(6),
	}

	it := instancesClient.AggregatedList(ctx, req)
	fmt.Fprintf(w, "Instances found:\n")
	// 尽管使用了`MaxResults`参数,但您不需要自己处理分页。
	// 返回的迭代器对象会自动处理分页,当您遍历结果时,会返回分隔的页面。

	for {
		pair, err := it.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return err
		}
		instances := pair.Value.Instances
		if len(instances) > 0 {
			fmt.Fprintf(w, "%s\n", pair.Key)
			for _, instance := range instances {
				fmt.Fprintf(w, "- %s %s\n", instance.GetName(), instance.GetMachineType())
			}
		}
	}

	return nil
}

上述代码虽然可能不太美观,但可以正常工作。

以下是我将该模块移动/转换为Restful API的努力:

package handlers

import (
	"context"
	"fmt"
	"net/http"

	compute "cloud.google.com/go/compute/apiv1"
	"google.golang.org/api/iterator"
	computepb "google.golang.org/genproto/googleapis/cloud/compute/v1"
	"google.golang.org/protobuf/proto"
)

// 使用Google Cloud compute API获取实例虚拟机实例列表
func (s *Server) getListAllInstances(w http.ResponseWriter, r *http.Request) error {

	ctx := context.Background()
	instancesClient, err := compute.NewInstancesRESTClient(ctx)

	if err != nil {
		return fmt.Errorf("NewInstancesRESTClient: %v", err)
	}
	defer instancesClient.Close()

	// 使用`MaxResults`参数限制API每个响应页面返回的结果数。
	req := &computepb.AggregatedListInstancesRequest{
		Project:    "unqie-string-id",
		MaxResults: proto.Uint32(16),
	}

	it := instancesClient.AggregatedList(ctx, req)
	fmt.Fprintf(w, "Instances found:\n")
	// 尽管使用了`MaxResults`参数,但您不需要自己处理分页。
	// 返回的迭代器对象会自动处理分页,当您遍历结果时,会返回分隔的页面。

	for {
		pair, err := it.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return err
		}
		instances := pair.Value.Instances
		if len(instances) > 0 {
			w.WriteHeader(http.StatusOK)
			fmt.Fprintf(w, "%s\n", pair.Key)
			for _, instance := range instances {
				fmt.Fprintf(w, "- %s %s\n", instance.GetName(), instance.GetMachineType())
			}
		}
	}

	return nil

}

ParentId是问题的原因(请向下滚动查看完整错误)。我插入的字符串在上述代码中似乎无法工作。Google Cloud API正在尝试确定项目的父ID是什么。
如何修复上述代码?

我将保留下面的代码供参考


这是我的api用来获取活动虚拟机列表的路径

package handlers

import "skeleton/api/middlewares"

func (s *Server) InitializeRoutes() {

	s.Router.HandleFunc("/compute", middlewares.MiddlewaresJSON(s.getListAllInstances)).Methods("GET")

}

这是我的MiddlewaresJSON

package middlewares

import (
	"log"
	"net/http"
)

// 拦截传入的请求,并将其中一个标头设置为Content-Type: application/json
func MiddlewaresJSON(next http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		// 记录路由和方法
		log.Println("== route: " + r.URL.Path)
		log.Println("== method: " + r.Method)

		// 修改标头
		w.Header().Set("Content-Type", "application/json")
		next(w, r)
	}
}

这是完整的错误信息:

cloud.google.com/go/compute/apiv1
..\go\pkg\mod\cloud.google.com\go@v0.97.0\compute\apiv1\firewall_policies_client.go:684:32: invalid operation: req.ParentId != nil (mismatched typen: req.ParentId != nil (mismatched types string and nil)

这是错误所指的库中的代码:

	if req != nil && req.ParentId != nil {
		params.Add("parentId", fmt.Sprintf("%v", req.GetParentId()))
	}
英文:

I'm trying to create a Go RESTful API that connects to Google Cloud API's.

An issue is happening, described as:
invalid operation: req.ParentId != nil (mismatched types string and nil)

Before creating the local API, I managed to write a Go module that could connect, authenticate, and pull data from Google Cloud. I'm now migrating that module to become a Restful API with paths.

The point of the module was to get a list of all current running Virtual Machines.

Here is the module before changing it to a restful API (which worked):

package main

import (
	&quot;fmt&quot;

	&quot;example.com/compute&quot;

	&quot;bytes&quot;
)

func main() {
	buf := new(bytes.Buffer)

	// Get a message and print it.
	r.HandleFunc(&quot;/virtualmachines&quot;, ListAllInstances)
	err := compute.ListAllInstances(buf, &quot;unique-string-id&quot;)
	if err != nil {
		panic(err)
	}
	fmt.Println(buf.String()) // &lt;======= Print buf contents!
}


// new file:

package compute

// [START compute_instances_list_all]
import (
	&quot;context&quot;
	&quot;fmt&quot;
	&quot;io&quot;

	compute &quot;cloud.google.com/go/compute/apiv1&quot;
	&quot;google.golang.org/api/iterator&quot;
	computepb &quot;google.golang.org/genproto/googleapis/cloud/compute/v1&quot;
	&quot;google.golang.org/protobuf/proto&quot;
)

// listAllInstances prints all instances present in a project, grouped by their zone.
func ListAllInstances(w io.Writer, projectID string) error {
	// projectID := &quot;your_project_id&quot;
	ctx := context.Background()
	instancesClient, err := compute.NewInstancesRESTClient(ctx)


	if err != nil {
		return fmt.Errorf(&quot;NewInstancesRESTClient: %v&quot;, err)
	}
	defer instancesClient.Close()

	// Use the `MaxResults` parameter to limit the number of results that the API returns per response page.
	req := &amp;computepb.AggregatedListInstancesRequest{
		Project:    projectID,
		MaxResults: proto.Uint32(6),
	}

	it := instancesClient.AggregatedList(ctx, req)
	fmt.Fprintf(w, &quot;Instances found:\n&quot;)
	// Despite using the `MaxResults` parameter, you don&#39;t need to handle the pagination
	// yourself. The returned iterator object handles pagination
	// automatically, returning separated pages as you iterate over the results.

	for {
		pair, err := it.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return err
		}
		instances := pair.Value.Instances
		if len(instances) &gt; 0 {
			fmt.Fprintf(w, &quot;%s\n&quot;, pair.Key)
			for _, instance := range instances {
				fmt.Fprintf(w, &quot;- %s %s\n&quot;, instance.GetName(), instance.GetMachineType())
			}
		}
	}

	return nil
}

The above worked well, even though it might not like pretty.

Below is my effort to move/transition the module to a Restful API:

package handlers

import (
	&quot;context&quot;
	&quot;fmt&quot;
	&quot;net/http&quot;

	compute &quot;cloud.google.com/go/compute/apiv1&quot;
	&quot;google.golang.org/api/iterator&quot;
	computepb &quot;google.golang.org/genproto/googleapis/cloud/compute/v1&quot;
	&quot;google.golang.org/protobuf/proto&quot;
)

// use Google Cloud compute API to get the list of instance virtual machine instances
func (s *Server) getListAllInstances(w http.ResponseWriter, r *http.Request) error {

	ctx := context.Background()
	instancesClient, err := compute.NewInstancesRESTClient(ctx)

	if err != nil {
		return fmt.Errorf(&quot;NewInstancesRESTClient: %v&quot;, err)
	}
	defer instancesClient.Close()

	// Use the `MaxResults` parameter to limit the number of results that the API returns per response page.
	req := &amp;computepb.AggregatedListInstancesRequest{
		Project:    &quot;unqie-string-id&quot;,
		MaxResults: proto.Uint32(16),
	}

	it := instancesClient.AggregatedList(ctx, req)
	fmt.Fprintf(w, &quot;Instances found:\n&quot;)
	// Despite using the `MaxResults` parameter, you don&#39;t need to handle the pagination
	// yourself. The returned iterator object handles pagination
	// automatically, returning separated pages as you iterate over the results.

	for {
		pair, err := it.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return err
		}
		instances := pair.Value.Instances
		if len(instances) &gt; 0 {
			w.WriteHeader(http.StatusOK)
			fmt.Fprintf(w, &quot;%s\n&quot;, pair.Key)
			for _, instance := range instances {
				fmt.Fprintf(w, &quot;- %s %s\n&quot;, instance.GetName(), instance.GetMachineType())
			}
		}
	}

	return nil

}

ParentId is the culprit (scroll below for the full error). The string I inserted does not seem to work in the code above. Google Cloud API is trying to figure out what parent ID is for the project.
How can I fix the code above?

Il leave this code below just for reference


Here is the path that my api uses to pull the list of active virtual machines

package handlers

import &quot;skeleton/api/middlewares&quot;

func (s *Server) InitializeRoutes() {

	s.Router.HandleFunc(&quot;/compute&quot;, middlewares.MiddlewaresJSON(s.getListAllInstances)).Methods(&quot;GET&quot;)

}

here is my MiddlewaresJSON:

package middlewares

import (
	&quot;log&quot;
	&quot;net/http&quot;
)

// intercept the incoming request, and set one of the headers to Content-Type: application/json
func MiddlewaresJSON(next http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		// log the route and method
		log.Println(&quot;== route: &quot; + r.URL.Path)
		log.Println(&quot;== method: &quot; + r.Method)

		// modify the header
		w.Header().Set(&quot;Content-Type&quot;, &quot;application/json&quot;)
		next(w, r)
	}
}

Here is the full error:

cloud.google.com/go/compute/apiv1
..\go\pkg\mod\cloud.google.com\go@v0.97.0\compute\apiv1\firewall_policies_client.go:684:32: invalid operation: req.ParentId != nil (mismatched typen: req.ParentId != nil (mismatched types string and nil)

Here is the code in the library that error is referring too:

	if req != nil &amp;&amp; req.ParentId != nil {
		params.Add(&quot;parentId&quot;, fmt.Sprintf(&quot;%v&quot;, req.GetParentId()))
	}

答案1

得分: 1

我遇到了同样的问题,通过降级一个提交来解决:

go get google.golang.org/genproto@81c1377

https://github.com/googleapis/go-genproto/commits/main

英文:

I had the same issue, solved by downgrading of 1 commit :

 go get google.golang.org/genproto@81c1377 

https://github.com/googleapis/go-genproto/commits/main

答案2

得分: 0

这是你的代码中的错误,而不是出版物中的错误。在你的代码中,Project字段的值应该是"unqie-string-id",而不是"unqie-string-id,"。正确的代码应该是:

req := &computepb.AggregatedListInstancesRequest{
        Project:    "unqie-string-id",
        MaxResults: proto.Uint32(16),
    }
英文:

Is it error in your code or just in publication?
in publication I see

req := &amp;computepb.AggregatedListInstancesRequest{
Project:    &quot;unqie-string-id,
MaxResults: proto.Uint32(16),
}

but should be

req := &amp;computepb.AggregatedListInstancesRequest{
Project:    &quot;unqie-string-id&quot;,
MaxResults: proto.Uint32(16),
}

huangapple
  • 本文由 发表于 2021年11月30日 09:39:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/70163288.html
匿名

发表评论

匿名网友

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

确定