【问题标题】:There is no way to use variable using range没有办法使用范围使用变量
【发布时间】:2017-07-20 04:11:04
【问题描述】:

我编写了一个简单的脚本,它将读取 /proc/cpuinfo 并返回一个包含内核信息的 []map[string]string

问题是我无法使用范围内的值,它总是给我最后一个 CPU 的信息。

我尝试在任何地方都使用闭包,但没有成功。而且我还尝试在循环中本地复制变量,但仍然没有成功。

这是我的代码

func GetCpuInfo() CpuInfo {
    cpus, err := os.Open("/proc/cpuinfo")
    if err != nil {
        log.Fatalln("Cannot open /proc/cpuinfo")
    }
    defer cpus.Close()
    s := bufio.NewScanner(cpus)
    cpuCores := make(CpuCores, 0)
    core := map[string]string{}
    for s.Scan() {
        txt := s.Text()
//copying the variable also does not work
        core := core

        if len(txt) == 0 {
//tried to use closure here with no success
            cpuCores = append(cpuCores, core)
            continue
        }
        fields := strings.Split(txt, ":")
        if len(fields) < 2 {
            continue
        }
//using closure here wont work either
        var k, v = strings.TrimSpace(fields[0]), strings.TrimSpace(fields[1])
        core[k] = v
    }
    return CpuInfo{
        Cores:    cpuCores,
        CpuCount: uint(runtime.NumCPU()),
        Brand:    cpuCores[0]["vendor_id"],
        Model:    cpuCores[0]["model name"],
    }
}

正如您从代码中看到的那样,似乎没有办法使用这个变量,或者我真的错过了一些重要的点。

【问题讨论】:

  • 为什么有核心图和名单?似乎您仅在 txt == 0 时附加到 cpuCores,否则将内容放入核心映射中,但在您的返回值中您仅使用 cpuCores。

标签: function loops go scope closures


【解决方案1】:

好像你想做这样的事情:

struct CpuCore {
    VendorID string
    ModelName string
}

func GetCpuInfo() CpuInfo {
    cpus, err := os.Open("/proc/cpuinfo")
    if err != nil {
        log.Fatalln("Cannot open /proc/cpuinfo")
    }
    defer cpus.Close()
    s := bufio.NewScanner(cpus)
    cpuCores := make(CpuCore, 0)
    for s.Scan() {
        txt := s.Text()

        fields := strings.Split(txt, ":")

        if len(fields) < 2 {
            continue
        }

        var k, v = strings.TrimSpace(fields[0]), strings.TrimSpace(fields[1])
        cpuCores = append(cpuCores, CpuCores{VendorID: k, ModelName: v})
    }
    return CpuInfo{
        Cores:    cpuCores,
        CpuCount: uint(runtime.NumCPU()),
        Brand:    cpuCores[0].VendorID,
        Model:    cpuCores[0].ModelName,
    }
}

我假设您有一个结构体 CpuCore,并且您想要创建一个名为 cpuCores 的数组。

也许如果您包含更多代码和类型,可以让我们实际尝试运行此代码。

【讨论】:

  • 实际上 cpu 核心是一个包含有关单个核心 /proc/cpuinfo 提供的所有数据的地图,在我的机器中有 4 个核心,所以我想最终得到一张大小为 4 的地图4 个条目,但问题是它们只是最后的 cpu 信息
  • 啊。因此,每次循环都需要实例化一个新地图。不要在循环之外创建core,而是在循环中创建它,你应该没问题。现在,您正在创建一个列表,其中包含对完全相同的地图的四个引用,您一直用最后一个值覆盖这些地图。
  • 也就是说,我认为在 go 中为此使用 Struct 更为惯用。
  • 我无法创建,因为在每次迭代中都会在地图中添加一些新的东西,是的,结构可能更酷,但我从 /proc/cpuinfo 读取,我不想编写结构并手动分配所有变量我从 cpuinfo 文件中获取这就是我使用地图的原因
  • 你认为我下面的方法会导致内存泄漏实际上我认为 gc 会处理垃圾信息
【解决方案2】:

我刚刚通过在添加核心变量后重置核心变量找到了解决方法

if len(txt) == 0 {
                cpuCores = append(cpuCores, core)
                core=map[string]string{}
            }

像这样,但我不确定这是否会导致内存泄漏

【讨论】:

    【解决方案3】:

    //copying the variable also does not work core := core 在 golang 中,地图类型是引用类型,我们不能通过:= 复制地图。

    你应该在每个循环中制作一张新地图。

    【讨论】:

      猜你喜欢
      • 2019-12-21
      • 1970-01-01
      • 2015-08-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-01
      • 2010-10-20
      • 1970-01-01
      相关资源
      最近更新 更多