我在代码中创建了一个客户类型。我有一个函数正在读取 csv 文件并从每一行创建一个数组。
type DesiredService struct {
Name string `json:"Name"`
Status string `json:"Status"`
}
如果我打印出变量,我有一些看起来像
[{app1 active}{app2 active}]
我不知道如何使用该变量并遍历每个索引。我需要获取所有状态为事件的条目并调用另一个函数来根据 API 检查名称。我在想也许我没有正确设置结构。
当我检查变量类型时,它返回 []main.DesiredService
在阅读了一些文档之后,这是我想出的但行不通的方法。
func checkPagerDutyforService (serviceList []DesiredService) (bool){
var serviceExist bool()
for i, v := range serviceList {
if v == "active" {
checkIfServiceExist(i, serviceList)
serviceExist = true
} else {
if v != "active"{
serviceExist = false
}
}
}
return serviceExist
最佳答案
I need to take all of the entries with a Status of active and call another function to check the name against an API.
在 Go 中,您使用 for
进行迭代循环,通常使用 range
功能。
package main
import (
"fmt"
)
type DesiredService struct {
// The JSON tags are redundant here. See below.
Name string `json:"Name"`
Status string `json:"Status"`
}
func main() {
services := []DesiredService{
DesiredService{"foo", "Active"},
DesiredService{"bar", "Active"},
DesiredService{"baz", "Inactive"},
}
for _,service := range services {
if service.Status == "Active" {
fmt.Printf("%#v\n", service);
}
}
}
请注意,range
返回索引(即 0、1、2)和实际元素。如果你只想要索引,它是 for i := range services
但如果你只想要元素,它是 for _,service := range services
和 _
告诉 Go 你不需要那个返回值。
range
是 Go 非常强大和灵活的核心特性。如果您还没有达到 range
,我建议您至少停下来阅读 A Tour of Go和 Go By Example这将涵盖像这样的基本功能。然后阅读 Effective Go了解详情。
请注意,JSON 字段标签是不必要的。默认情况下,JSON 已经自动将字段 Name
编码为 JSON 字段 Name
。所以它们可以省略。如果您想将其更改为 name
,则需要使用标签。
您尝试的代码存在很多问题。
v == "active"
:v
是一个 DesiredService 结构。要检查其状态字段,它是v.Status == "active"
。else { if v != "active"
:这与if v == "active"
是多余的。如果你在else
定义的 block 中v == "active"
。return serviceExist
:这是由每次循环迭代设置的,因此它只会反射(reflect)serviceList
中的最后一个元素。
这是您处理此问题的方式。
// Just a placeholder. Presumably it will ping the service
// to ensure it's really working.
func pingService( service DesiredService ) bool {
return true
}
func getActiveService (services []DesiredService) *DesiredService {
for _, service := range services {
if service.Status == "active" && pingService(service) {
return &service
}
}
return nil
}
请注意,它会在找到事件服务后立即返回,而不是遍历整个列表。一旦找到服务,就无需再进行下一步。
出于两个原因,我已将其更改为 getActiveService
。这里没有关于寻呼机的任何内容,因此大概它可以处理任何类型的服务列表。其次,返回一个 bool 就像说“是的,这个列表中有一个活跃的服务”,下一个自然的问题是“好吧,自作聪明,哪个?!”既然我们已经完成了工作,不妨返回一个活跃的服务。
这会将返回值从一个简单的 bool 值稍微更改为 *DesiredService
。 “获取”功能有时无法获取您想要的内容。但是 DesiredService
类型表示您将总是返回一个DesiredService
。通过使其成为 DesiredService
的引用,如果没有事件服务,我们可以返回 nil
。
service := getActiveService(services);
if service != nil {
fmt.Println(service)
} else {
fmt.Println("No active service")
}
*DesiredService
是对 DesiredService
的引用,而不是副本。 Go 将消除事物和事物引用之间的差异,没有用于处理引用的特殊语法。但是,请注意您使用的不是副本。您对 service
所做的任何更改都将反射(reflect)在 services
列表中。
// This will affect the entry in services as well.
service.Name = "something else"
Further detailed errors are returned using the error
type .
下一步是将 service.Status == "active"&& pingService(service)
滚动到 a single method on DesiredService
所以服务知道如何检查自己。然后任何使用 DesiredService 的人都不需要知道这些细节,而且如果细节发生变化,它们都在一个地方。
func (self DesiredService) isActive() bool {
return self.Status == "active" && self.Ping()
}
Ping 也是服务应该对自己执行的操作。
// Just a placeholder. Presumably this will ping the
// service or something.
func (self DesiredService) Ping() bool {
return true
}
然后 getActiveService
询问 service
是否激活。
func getActiveService (serviceList []DesiredService) *DesiredService {
for _, service := range serviceList {
if service.isActive() {
return &service
}
}
return nil
}
关于go - 如何在 Go 中迭代自定义类型的数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48693172/