访问未导出的函数`not.string`

时间:2013-10-06 21:36:24

标签: go

我想将big.Int转换为简单的base32。不是标准的base32内容,如base32实现的 RFC 4648 zBase32 Crockford 我只需要简单的普通5位字符0-9A-V字符集。

我知道base32包并且它没有做我想要的 - 它使用填充和我不想要的东西在标准的基数32数字中构建结果。当然,我可以使用它并撕下尾随的“=”字符并破解剩下的东西,但这似乎是一个残酷的解决方案。

有一个big.SetString(string, base)可以解析字符串形式的base32号码,但没有反向 - 我正在寻找的是big.GetString(base),就像Java BigInteger.toString(int base)一样。

然而,nat.string确实完全我想要的东西。我怎样才能访问它?

有没有办法我可以手动扩展big来实施big.GetString(base),而nat.string使用正确的charset来调用big.nat

我是否有办法覆盖big使用nat.stringnat.trailingZeroBits使用{{1}}的未导出{{1}}?

我还能做些什么吗?

P.S。我也有兴趣使用{{1}} - 我必须自己编写,因为我没有意识到这已经完成了。

3 个答案:

答案 0 :(得分:2)

您根本无法访问未导出的功能。您需要重新编写nat.go的至少一部分才能实现该功能。其中一些函数看起来非常有用,因此可能值sending a feature request to the golang-nuts group要求在将来的版本中导出其中一些函数。

但是,您可以使用strconv.FormatInt()来执行您需要的操作。

给出big.Int b即可:

strconv.FormatInt(b.Int64(), 32)

完整示例:

package main

import (
    "fmt"
    "math/big"
    "strconv"
)

func main() {
    i := 3286583923486565782 // Some random integer
    b := big.NewInt(int64(i))
    fmt.Println(strconv.FormatInt(b.Int64(), 32))
}

产地:

  
    

2r72al99uq9cm

  

Playground

答案 1 :(得分:2)

我认为go团队不会导出nat中的任何内容,因为这是big.Int的实现细节。他们可能会看好ToBase来自big.Int的{​​{1}}功能。

与此同时,这是一款经过轻度测试的天真基础转换器

func ToBase(x *big.Int, base int) string {
    if x.Sign() == 0 {
        return "0"
    }
    y := new(big.Int).Set(x)
    b := big.NewInt(int64(base))
    charset := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    out := make([]byte, 0, 16)
    negative := false
    if y.Sign() < 0 {
        negative = true
        y.Neg(y)
    }
    digit := new(big.Int)
    for y.Sign() != 0 {
        y.DivMod(y, b, digit)
        out = append(out, charset[digit.Int64()])
    }
    if negative {
        out = append(out, '-')
    }
    // Reverse out
    for i, j := 0, len(out)-1; i < j; i, j = i+1, j-1 {
        out[i], out[j] = out[j], out[i]
    }
    return string(out)
}

Playground link

答案 2 :(得分:1)

我已经贴上了疯狂的帖子。他们似乎对我的建议感到满意。

同时 - 我的Base32实现(不处理符号 - nat

// The digits
const charset string = "0123456789ABCDEFGHIJKLMNOPQRSTUV"

/*
 Convert the big to base32
*/
func Base32(n big.Int) string {
    // The bytes of the number
    bytes := n.Bytes()
    nBytes := len(bytes)
    if nBytes == 0 {
        // Special case 0.
        return "0"
    }
    // How many digits will be in the string?
    nBits := nBytes * 8
    nDigits := nBits / 5
    if nBits%5 > 0 {
        nDigits += 1
    }
    // Grow the digits into an array
    digits := make([]byte, nDigits)
    digit := nDigits - 1
    // Peel off 5 bits from the array each time.
    for b, shr := nBytes-1, uint(0); b >= 0; {
        // The next lot is there.
        shrp5 := shr + 5
        // Build my bits.
        x := (bytes[b] >> shr)
        if shrp5 > 8 && b > 0 {
            of := shrp5 - 8
            // Add in some bits from the next byte too.
            x &= (1 << (8 - shr)) - 1
            x |= bytes[b-1] << (5 - of)
        }
        // Shift 5 more.
        shr = shrp5
        // Should we step to next byte?
        if shr >= 8 {
            // Next byte
            shr -= 8
            b -= 1
        }
        x &= 0x1f
        // Build my digit
        digits[digit] = charset[x]
        digit -= 1
    }
    // Skip leading zeros.
    lz := 0
    for digits[lz] == '0' {
        lz += 1
    }
    // Return the string equivalent.
    return string(digits[lz:])
}

欢迎评论。