dongshen9058 2018-02-08 19:16
浏览 76
已采纳

如何在Go中迭代自定义类型的数组?

I have a customer type I have created in my code. I have a function that is reading in a csv file and creating an array from each line.

type DesiredService struct {
    Name string `json:"Name"`
    Status string `json:"Status"`
}

If I print out the variable I have something that looks like [{app1 active}{app2 active}]

I can not figure out how I would take that variable and iterate over each index. I need to take all of the entries with a Status of active and call another function to check the name against an API. I am thinking maybe I did not set the struct up correctly.

When I check the variable type it returns []main.DesiredService

After reading some of the docs this is what I came up with that is not working.

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
  • 写回答

1条回答 默认 最新

  • dream_wu2015 2018-02-08 19:32
    关注

    I need to take all of the entries with a Status of active and call another function to check the name against an API.

    In Go you iterate with a for loop, usually using the range function.

    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
    ", service);
            }
        }
    }
    

    Note that range returns the index (ie. 0, 1, 2) and the actual element. If you want just the index it's for i := range services but if you want just the element it's for _,service := range services with the _ telling Go that you don't want that return value.

    range is very powerful and flexible core feature of Go. If you haven't gotten to range, I'd recommend stopping and reading at least A Tour of Go and Go By Example which will cover basic functionality like this. Then read Effective Go for the details.


    Note that the JSON field tags are unnecessary. JSON will already automatically marshal the field Name as the JSON field Name by default. So they can be omitted. If you wanted to change it to name then you'd use a tag.


    There's a number of problems with the code you're trying.

    • v == "active": v is a DesiredService struct. To check its Status field it's v.Status == "active".
    • else { if v != "active": This is redundant with if v == "active". If you're in that else block by definition v == "active".
    • return serviceExist: This is set by every loop iteration, so it will only reflect the last element in serviceList.

    Here's how you'd handle this.

    // 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
    }
    

    Note that it returns immediately upon finding an active service, rather than iterating through the whole list. Once it's found a service there's no need to go further.

    I've changed it to getActiveService for two reasons. There's nothing in here about pagers, so presumably it can handle lists of any types of services. And second, returning a bool is like saying "yes, there is an active service in this list" and the natural next question is "ok, smart ass, which one?!" Since we've gone through the work anyway, might as well return an active service.

    This changes the return value a bit from a simple boolean to *DesiredService. "Get" functions sometimes can't get what you want. But the DesiredService type says you will always return a DesiredService. By making it a reference to a DesiredService we can return nil if there's no active service.

    service := getActiveService(services);
    if service != nil {
        fmt.Println(service)
    } else {
        fmt.Println("No active service")
    }
    

    *DesiredService is a reference to DesiredService not a copy. Go will smooth out the difference between a thing and a reference to a thing, there's no special syntax for working with a reference. However, be aware that you're not working with a copy. Any changes you make to service will reflect on the services list.

    // This will affect the entry in services as well.
    service.Name = "something else"
    

    Further detailed errors are returned using the error type.


    The next step would be to roll service.Status == "active" && pingService(service) into a single method on DesiredService so services know how to check themselves. Then anyone using a DesiredService doesn't need to know these details, and the details are in one place should they change.

    func (self DesiredService) isActive() bool {
        return self.Status == "active" && self.Ping()
    }
    

    Pinging is also something a service should do to itself.

    // Just a placeholder. Presumably this will ping the
    // service or something.
    func (self DesiredService) Ping() bool {
        return true
    }
    

    Then getActiveService asks the service if it is active.

    func getActiveService (serviceList []DesiredService) *DesiredService {
        for _, service := range serviceList {
            if service.isActive() {
                return &service
            }
        }
    
        return nil
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 关于大棚监测的pcb板设计
  • ¥20 sim800c模块 at指令及平台
  • ¥15 stm32开发clion时遇到的编译问题
  • ¥15 lna设计 源简并电感型共源放大器
  • ¥15 如何用Labview在myRIO上做LCD显示?(语言-开发语言)
  • ¥15 Vue3地图和异步函数使用
  • ¥15 C++ yoloV5改写遇到的问题
  • ¥20 win11修改中文用户名路径
  • ¥15 win2012磁盘空间不足,c盘正常,d盘无法写入
  • ¥15 用土力学知识进行土坡稳定性分析与挡土墙设计