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 乌班图ip地址配置及远程SSH
  • ¥15 怎么让点阵屏显示静态爱心,用keiluVision5写出让点阵屏显示静态爱心的代码,越快越好
  • ¥15 PSPICE制作一个加法器
  • ¥15 javaweb项目无法正常跳转
  • ¥15 VMBox虚拟机无法访问
  • ¥15 skd显示找不到头文件
  • ¥15 机器视觉中图片中长度与真实长度的关系
  • ¥15 fastreport table 怎么只让每页的最下面和最顶部有横线
  • ¥15 java 的protected权限 ,问题在注释里
  • ¥15 这个是哪里有问题啊?