使用Go进行CPU ID的ID掩码转换

时间:2016-10-25 08:50:07

标签: string go binary binary-operators

我有一个掩码,其中包含cpu_ids的二进制计数(3个CPU的CALayer),我想将其转换为逗号分隔的0xA00000800000 cpu_ids:string

我做了以下Go实现(我是Go的首发)。这是最好的方式吗?特别是字节缓冲区的处理似乎效率低下!

"0,2,24"

返回:

  

" 0,2,24"

1 个答案:

答案 0 :(得分:3)

你正在做的事实上是从左到右输出二进制表示中的"1"的索引,并从左边开始索引计数(不可用)。 / p>

您可以使用位掩码和按位运算符实现相同的操作,而无需将其转换为二进制字符串。我会返回一段索引而不是格式化的字符串,更容易使用。

要测试最低(最右边)位是1,可以像x&0x01 == 1那样进行,并将整数按位向右移动:x >>= 1。移位后,最右边的位"消失",之前的第2位成为第1位,因此您可以使用相同的逻辑再次测试。您可以循环直到该数字大于0(这意味着它有1位)。

有关按位操作的更多示例,请参阅此问题:Difference between some operators "|", "^", "&", "&^". Golang

当然,如果我们测试最右边的位并向右移动,我们得到 reverse 顺序的位(索引)(与你想要的相比),并且索引是从右边计算的,所以我们在返回结果之前必须纠正这个问题。

所以解决方案看起来像这样:

func getCpuIds(cpuMap string) (r []int) {
    ci, err := strconv.ParseInt(cpuMap, 0, 64)
    if err != nil {
        panic(err)
    }

    count := 0
    for ; ci > 0; count, ci = count+1, ci>>1 {
        if ci&0x01 == 1 {
            r = append(r, count)
        }
    }

    // Indices are from the right, correct it:
    for i, v := range r {
        r[i] = count - v - 1
    }
    // Result is in reverse order:
    for i, j := 0, len(r)-1; i < j; i, j = i+1, j-1 {
        r[i], r[j] = r[j], r[i]
    }

    return
}

输出(在Go Playground上尝试):

[0 2 24]

如果由于某种原因你需要以逗号分隔string的结果,这就是你如何获得它:

buf := &bytes.Buffer{}
for i, v := range cpuIds {
    if i > 0 {
        buf.WriteString(",")
    }
    buf.WriteString(strconv.Itoa(v))
}
cpuIdsStr := buf.String()
fmt.Println(cpuIdsStr)

输出(在Go Playground上尝试):

0,2,24