Display base 10 representation of huge hexa string? - go

Trying to find how to have this hexa string "58068906d6194c6cbda7a6df" into it's base 10 representation.
I tried with this:
i, err := strconv.Parse("58068906d6194c6cbda7a6df", 16, 64)
Obviously I'm getting this error: parsing "58068906d6194c6cbda7a6df"; value out of range
I also need to take the base 10 string representation and get this hexa value back after some processing. i.e.:
base10 := "58068906d6194c6cbda7a6df" => to base 10 string
some processing
hexa := base10 => to base 16 string
Can I use the fmt package to dislpay the base 10? I know that displaying the hexa of a base 10 I could use %x, but what can I do with an existing string?
Thanks for your help, for a reason I cannot understand, I'm unable to find any way to do this.

Your hex value is larger than int64 can hold, so you have to use a big.Int
https://play.golang.org/p/OPPL43u6nB
i := new(big.Int)
i.SetString("58068906d6194c6cbda7a6df", 16)
fmt.Println(i)
To get a hex string representation from a big.Int, you can use the Text method:
hex := i.Text(16)

Related

Converting Hex to signed Int in Go

I want to convert a hex string to a signed integer Value in Go. My input value is "FF60" and I want the output to be "-160". When I use the following function, the result is "65376", which represents the unsigned representation.
value, err := strconv.ParseInt("FF60", 16, 64)
I would have expected the outcome of 65376 when using the ParseUInt function.
Any help would be really appreciated.
The third parameter of strconv.ParseInt() tells the bitsize of the integer you want to parse. 0xff60 parsed as a 64-bit integer is indeed 65376.
You actually want to parse it as a 16-bit integer, so pass 16 as the bitsize. Doing so you will get an error though:
strconv.ParseInt: parsing "FF60": value out of range
Which is true: 0xFF60 (which is 65376) is outside of the valid range of int16 (valid int16 range is [-32768..32767]).
So what you may do is parse it as an unsigned 16-bit integer using strconv.ParseUint(), then convert the result to a signed 16-bit integer:
value, err := strconv.ParseUint("FF60", 16, 16)
fmt.Println(value, err)
fmt.Println(int16(value))
This will output (try it on the Go Playground):
65376 <nil>
-160

Cannot convert byte to int in Golang

This is strange but I cannot convert byte value into int.
Here is the code:
fmt.Println("numMsgsByte is:", numMsgsByte)
numMsgsStr := string(numMsgsByte)
fmt.Println("numMsgsStr is:", numMsgsStr)
numMsgs, err = strconv.Atoi(numMsgsStr)
if err != nil {
log.Println("error in msg conversion", err)
return 0
}
The terminal print out:
numMsgsByte is: [5]
numMsgsStr is:
counter.go:51: error in msg conversion strconv.Atoi: parsing "\x05": invalid syntax
What could be wrong here? How can I fix it?
numMsgByte is not a byte, it is a []byte, which contains 5 (not "5"). When you convert it to string using string(numMsgByte), you get a string "\x5".
What you need is: int(numMsgType[0])
The correct way to get an integer out of Redis using redigo would be to just use redis.Int in the first place, instead of using redis.Bytes and trying to convert the result to an int yourself.
In general though, to convert an arbitrary byte array to the integer it represents, you would use the encoding/binary package. You'll need to know some key details about the byte array though:
Does it represent a signed or unsigned value?
Of what width? 32 bit? 64 bit?
Of what byte order? Big-endian? Little-endian?
Are you sure it's represented as an integer, not e.g. a float, or a string representation of a number?
To quote the example from the docs:
b := []byte{0xe8, 0x03, 0xd0, 0x07}
x1 := binary.LittleEndian.Uint16(b[0:])
x2 := binary.LittleEndian.Uint16(b[2:])
fmt.Printf("%#04x %#04x\n", x1, x2)

How to cut uuid in golang?

In order to make semi-random slugs, I'd like to use first 8 characters of uuid. So I have
import (
fmt
"github.com/satori/go.uuid"
)
u1 := uuid.NewV4()
fmt.Println("u1 :", u1)
runes := []rune(u1)
slug := string(runes[0:7])
But in compile time I get this error:
cannot convert u1 (type uuid.UUID) to type []rune
How can I fix it?
There is no need to convert the UUID to a []rune. That UUID type is stored in a binary representation as a [16]byte. There is a UUID.String() method which you can use to convert to a string, then slice it.
slug := u1.String()[:7]
In that package (I just looked at the source code) a UUID is an alias for [16]byte, so you cannot concert it to a rune array, not that you want to.
Try this:
s := hex.EncodeToString(u1.Bytes()[:4])
This will give you 8 hex digits. However, this is still a roundabout way of doing things. A v4 UUID is random except for certain bits, so if you are not using the whole UUID it is more straightforward to just generate 4 random bytes. Use the Read() function in math/rand (which must be seeded) or crypto/rand (which is what the UUID library uses).
b := make([]byte, 4)
rand.Read(b) // Doesn’t actually fail
s := hex.EncodeToString(b)

golang simplejson mustint64 doesn't convert from string to int64

I am using simplejson, and it provides type asserters.
fmt.Printf("%s %s", m.Get("created_time").MustString(), m.Get("created_time").MustInt64())
above code shows this result:
1506259900 %!s(int64=0)
So MustInt64() gives 0 instead of converted Int64 value.
Is it because the 1506259900 is too big to be converted?
Thank for your help!
The original json was:
{"created_time":"1505733738"}
Not
{"created_time":1505733738}
It's originally a STRING, not a NUMBER.
So, when use MustInt64() to that json, it should return 0 because type is not matched.
Right way to treat this is using strconv.
i64, err := strconv.ParseInt(m.Get("created_time").MustString(), 10, 64)
And you'll get what you wanted as i64.

Umlauts and slices

I'm having some trouble while reading a file which has a fixed column length format. Some columns may contain umlauts.
Umlauts seem to use 2 bytes instead of one. This is not the behaviour I was expecting. Is there any kind of function which returns a substring? Slice does not seem to work in this case.
Here's some sample code:
http://play.golang.org/p/ZJ1axy7UXe
umlautsString := "Rhön"
fmt.Println(len(umlautsString))
fmt.Println(umlautsString[0:4])
Prints:
5
Rhö
In go, a slice of a string counts bytes, not runes. This is why "Rhön"[0:3] gives you Rh and the first byte of ö.
Characters encoded in UTF-8 are represented as runes because UTF-8 encodes characters in more than one
byte (up to four bytes) to provide a bigger range of characters.
If you want to slice a string with the [] syntax, convert the string to []rune before.
Example (on play):
umlautsString := "Rhön"
runes = []rune(umlautsString)
fmt.Println(string(runes[0:3])) // Rhö
Noteworthy: This golang blog post about string representation in go.
You can convert string to []rune and work with it:
package main
import "fmt"
func main() {
umlautsString := "Rhön"
fmt.Println(len(umlautsString))
subStrRunes:= []rune(umlautsString)
fmt.Println(len(subStrRunes))
fmt.Println(string(subStrRunes[0:4]))
}
http://play.golang.org/p/__WfitzMOJ
Hope that helps!
Another option is the utf8string package:
package main
import "golang.org/x/exp/utf8string"
func main() {
s := utf8string.NewString("🧡💛💚💙💜")
// example 1
n := s.RuneCount()
println(n == 5)
// example 2
t := s.Slice(0, 2)
println(t == "🧡💛")
}
https://pkg.go.dev/golang.org/x/exp/utf8string

Resources