英文:
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 (
"fmt"
"example.com/compute"
"bytes"
)
func main() {
buf := new(bytes.Buffer)
// Get a message and print it.
r.HandleFunc("/virtualmachines", ListAllInstances)
err := compute.ListAllInstances(buf, "unique-string-id")
if err != nil {
panic(err)
}
fmt.Println(buf.String()) // <======= Print buf contents!
}
// new file:
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 prints all instances present in a project, grouped by their zone.
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()
// Use the `MaxResults` parameter to limit the number of results that the API returns per response page.
req := &computepb.AggregatedListInstancesRequest{
Project: projectID,
MaxResults: proto.Uint32(6),
}
it := instancesClient.AggregatedList(ctx, req)
fmt.Fprintf(w, "Instances found:\n")
// Despite using the `MaxResults` parameter, you don'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) > 0 {
fmt.Fprintf(w, "%s\n", pair.Key)
for _, instance := range instances {
fmt.Fprintf(w, "- %s %s\n", 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 (
"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"
)
// 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("NewInstancesRESTClient: %v", err)
}
defer instancesClient.Close()
// Use the `MaxResults` parameter to limit the number of results that the API returns per response page.
req := &computepb.AggregatedListInstancesRequest{
Project: "unqie-string-id",
MaxResults: proto.Uint32(16),
}
it := instancesClient.AggregatedList(ctx, req)
fmt.Fprintf(w, "Instances found:\n")
// Despite using the `MaxResults` parameter, you don'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) > 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
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 "skeleton/api/middlewares"
func (s *Server) InitializeRoutes() {
s.Router.HandleFunc("/compute", middlewares.MiddlewaresJSON(s.getListAllInstances)).Methods("GET")
}
here is my MiddlewaresJSON
:
package middlewares
import (
"log"
"net/http"
)
// 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("== route: " + r.URL.Path)
log.Println("== method: " + r.Method)
// modify the header
w.Header().Set("Content-Type", "application/json")
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 && req.ParentId != nil {
params.Add("parentId", fmt.Sprintf("%v", 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
答案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 := &computepb.AggregatedListInstancesRequest{
Project: "unqie-string-id,
MaxResults: proto.Uint32(16),
}
but should be
req := &computepb.AggregatedListInstancesRequest{
Project: "unqie-string-id",
MaxResults: proto.Uint32(16),
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论