Convert binary value as string to uint32 in Golang - go

Hello i am trying to convert 00000000000000000000000000001011 to uint32 in golang using
var v = "00000000000000000000000000001011"
fmt.Printf("%T\n", v)
c := []byte(v)
u := binary.LittleEndian.Uint32(c)
However it is not working.

You can't use encoding/binary for this, as that is to serialize and deserialize the (memory) bytes of different values (e.g. numbers). What you have is the base 2 string representation of the number.
To get its integer value you have to parse it. For that, use strconv.ParseUint():
s := "00000000000000000000000000001011"
u, err := strconv.ParseUint(s, 2, 32)
if err != nil {
panic(err)
}
fmt.Println(u)
This outputs (try it on the Go Playground):
11
Note that strconv.ParseUint() returns a value of type uint64, so if you need uint32, you have to manually convert it, e.g.:
u32 := uint32(u)
There are more options for parsing numbers from strings, for an overview, check Convert string to integer type in Go?

For example,
package main
import (
"fmt"
"strconv"
)
func main() {
s := "00000000000000000000000000001011"
fmt.Println(s)
u64, err := strconv.ParseUint(s, 2, 32)
u32 := uint32(u64)
if err == nil {
fmt.Println(u32)
}
}
Playground: https://play.golang.org/p/yiicgWsb7B_M
Output:
00000000000000000000000000001011
11

Related

What happen when field value string is unmarshalled into []byte

What happens to my original data in the variable str here?
After converting to the struct the length of bytes is 6
And the value of byte don't match ascii code of 1, 2, 3, 4, 5, 6, 7, 8 at all
package main
import (
"encoding/json"
"fmt"
)
type Encrypt struct {
Bytes []byte `json:"bytes"`
}
func main(){
str := "12345678"
raw := fmt.Sprintf("{\"bytes\":%s}", str)
var encrypt = Encrypt{}
fmt.Println([]byte(raw)[0])
err := json.Unmarshal([]byte(raw), &encrypt)
if err != nil{
fmt.Println(err)
return
}
fmt.Println("final result")
fmt.Println(len(encrypt.Bytes))
fmt.Println(string(encrypt.Bytes))
for _, b := range encrypt.Bytes{
fmt.Print(b)
fmt.Print(" ")
}
fmt.Print("\n")
}
As per the documentation https://pkg.go.dev/encoding/json#Unmarshal:
To unmarshal JSON into an interface value, Unmarshal stores one of these in the interface value:
bool, for JSON booleans
float64, for JSON numbers
string, for JSON strings
[]interface{}, for JSON arrays
map[string]interface{}, for JSON objects
nil for JSON null
As you can see there is no place for []byte. Also, in you code raw := fmt.Sprintf("{\"bytes\":%s}", str) you are sending str as a number. You can send it as string as in the following code.
package main
import (
"encoding/json"
"fmt"
)
type Encrypt struct {
ByteString string `json:"bytes"`
}
func main() {
str := "12345678"
raw := fmt.Sprintf("{\"bytes\":\"%s\"}", str)
fmt.Println(raw)
var encrypt = Encrypt{}
fmt.Println([]byte(str))
err := json.Unmarshal([]byte(raw), &encrypt)
if err != nil {
panic(err)
}
fmt.Println("final result ", []byte(encrypt.ByteString))
}

How to convert string from interface to []string in golang?

I'm parsing a JSON object which contains an array of strings :
var ii interface{}
json := "{\"aString\": [\"aaa_111\", \"bbb_222\"], \"whatever\":\"ccc\"}"
err := json.Unmarshal([]byte(json), &ii)
if err != nil {
log.Fatal(err)
}
data := ii.(map[string]interface{})
fmt.Println(data["aString"]) // outputs: ["aaa_111" "bbb_222"]
I tried to convert data["aString"] to []string to be able to loop over it, but it fails :
test := []string(data["aString"]).([]string)
fmt.Println(test) // panic -> interface conversion:
// interface is string, not []string
How can I convert data["aString"] ?
edit:
I didn't express myself properly. If I print data, I have such map :
map[aString:["BBB-222","AAA-111"] whatever:ccc]
I want to loop over aString (to manipule each array entry). But I can't find how, because aString is type interface {} :
for i, v := range aString { // <-- fails
// ...
fmt.Println(i, v)
}
That's why I want to convert aString. I don't want to convert a string which looks like an array to an array.
I recommend you move away from this implementation in general. Your json may vary but you can easily use objects and avoid all this type unsafe nonsense.
Anyway, that conversion doesn't work because the types inside the slice are not string, they're also interface{}. You have to iterate the collection then do a type assertion on each item like so:
aInterface := data["aString"].([]interface{})
aString := make([]string, len(aInterface))
for i, v := range aInterface {
aString[i] = v.(string)
}
Is it what you need?
package main
import (
"fmt"
"encoding/json"
)
func main() {
js := "{\"aString\": [\"aaa_111\", \"bbb_222\"], \"whatever\":\"ccc\"}"
a := make(map[string]interface{})
json.Unmarshal([]byte(js), &a)
for _, v := range a["aString"].([]interface{}) {
str := v.(string)
fmt.Println(str)
}
}
Check on Go Playground
For another approach, you can use a struct instead:
package main
import (
"encoding/json"
"fmt"
)
func main() {
s := []byte(`{"aString": ["aaa_111", "bbb_222"], "whatever":"ccc"}`)
var t struct {
Astring []string
Whatever string
}
json.Unmarshal(s, &t)
fmt.Printf("%+v\n", t) // {Astring:[aaa_111 bbb_222] Whatever:ccc}
}

Golang: parse a signed int

I have some code that needs to be able to parse a string containing a 64-bit value into an int64. For example, ff11223344556677 is valid, but a downstream system wants that in an int64.
strconv.ParseInt("ff11223344556677", 16, 64) gives a range error - it only likes to parse positive integers. Is there a way to go about putting this value into an int64 even though it is going to be negative?
For example,
package main
import (
"fmt"
"strconv"
)
func main() {
u, err := strconv.ParseUint("ff11223344556677", 16, 64)
fmt.Printf("%x %v\n", u, err)
i := int64(u)
fmt.Println(i)
}
Output:
ff11223344556677 <nil>
-67234915848722825

Why can't I access map key with an int?

I create a map like so:
board := make(map[int]map[string]string)
I add some numbers to it so data is formatted like follows.
1 : map("a", "b" ..)
I then pass in a position. "a1" and this is where I hit a wall.
func (checkers *Checkers) setPiece(piece string, coordinates string) {
lett := string(coordinates[0]);
num, err := strconv.ParseInt(string(coordinates[1]), 0, 64)
if err != nil {
panic("Invalid coordinate format")
}
row := checkers.board[num]
}
I get the follow error: 'cannot use num (type int64) as type int in map index'
Why do I get this error? How do I access a key in the map?
You just have to convert from int64 to int. like so:
checkers.board[int(num)]
However, if all you want is to parse an int out of a string, you should use strconv.AtoI for that. It will return (int, error) so you don't have to convert it. Also, keep in mind that the way your code is currently written will not work for 2-digit numbers or 2-letter prefixes. This may be by design.
Use
num, err := strconv.Atoi(string(coordinates[1]))
which returns an int.
Package strconv
func Atoi
func Atoi(s string) (i int, err error)
Atoi is shorthand for ParseInt(s, 10, 0).

Go precise decimals with mgo

I am writing an application where I use money and want very accurate numbers. I am also using mgo to store the results after some application. I was wondering if there was a way for me to use math.Rat or godec in a struct and have it store as a number in mgo?
This is the kind of code i was hoping to run:
package main
import(
"fmt"
"math/big"
"labix.org/v2/mgo"
)
var mgoSession *mgo.Session
type Test struct{
Budget big.Rat
}
func MongoLog(table string, pointer interface{}) {
err := mgoSession.DB("db_log").C(table).Insert(pointer)
if err != nil {
panic(err)
}
}
func main(){
var err error
mgoSession, err = mgo.Dial("localhost:27017")
defer mgoSession.Close()
if err != nil {
panic(err)
}
cmp := big.NewRat(1, 100000)
var test = Test{Budget : *big.NewRat(5, 10)}
MongoLog("test", &test)
for i := 0; i < 20; i++{
fmt.Printf("Printf: %s\n", test.Budget.FloatString(10))
fmt.Println("Println:", test.Budget, "\n")
test.Budget.Sub(&test.Budget, cmp)
// test.Budget = test.Budget - cpm
}
MongoLog("test", &test)
}
big.Rat is basically a pair of unexported int big.Int values describing the numerator and denominator of a rational number, respectively.
You can easily get both numbers through (*big.Rat).Denom and (*big.Rat).Num.
Then store them in a structure of your own, with exported (upper case) fields:
type CurrencyValue struct {
Denom int64
Num int64
}
Store this with mgo and convert it back to a *big.Rat in your application through big.NewRat
Edit:
Nick Craig-Wood in the comments correctly noted that big.Rat actually consists of 2 big.Int values, not int values as I had written (easy to miss the upper case i). It's hard to represent a big.Int in BSON but, int64 should cover most use-cases.

Resources