I have a hexademial string that I constructed from arduino sensor "5FEE012503591FC70CC8"
This value contains an array of with specific data placed at specific locations of the hex string. Using javascript I can convert the hexstring to a buffer then apply bit shifting operations to extract data, for example battery status like so
const bytes = new Buffer.from("5FEE012503591FC70CC8", "hex");
const battery = (bytes[8] << 8) | bytes[9];
console.log(battery)
My attemp works but I feel its not optimal like the js way I have shown above
package main
import (
"fmt"
"strconv"
)
func main() {
hex := "5FEE012503591FC70CC8"
bat, err := strconv.ParseInt(hex[16:20],16,64)
if err != nil {
panic(err)
}
fmt.Println("Battry: ",bat)
}
I would really appreciate if someone could show me how to work with buffers or equivalent to the js solution but in go. FYI the battery information is in the last 4 characters in the hex string
The standard way to convert a string of hex-digits into a bytes slice is to use hex.DecodeString:
import "encoding/hex"
bs, err := hex.DecodeString("5FEE012503591FC70CC8")
you can convert the last two bytes into an uint16 (unsigned since battery level is probably not negative) in the same fashion as your Javascript:
bat := uint16(bs[8])<< 8 | uint16(bs[9])
https://play.golang.org/p/eeCeofCathF
or you can use the encoding/binary package:
bat := binary.BigEndian.Uint16(bs[8:])
https://play.golang.org/p/FVvaofgM8W-
I have go script that starts on "localhost:8080/1" with a previous and next links I need to add Random link with custom range that I can change like:
small numbers like 100 to 200 "localhost:8080/100 - 200" and
even to big number like: "16567684686592643791596485465456223131545455682945955"
So:
// Get next and previous page numbers
previous := new(big.Int).Sub(page, one)
next := new(big.Int).Add(page, one)
random :=????
You need to use the package crypto.rand Int() function, which does support big.Int (as opposed to the math.rand package)
See this article (and its playground example):
package main
import (
"fmt"
"math/big"
"crypto/rand"
)
func main() {
var prime1, _ = new(big.Int).SetString("21888242871839275222246405745257275088548364400416034343698204186575808495617", 10)
// Generate random numbers in range [0..prime1]
// Ignore error values
// Don't use this code to generate secret keys that protect important stuff!
x, _ := rand.Int(rand.Reader, prime1)
y, _ := rand.Int(rand.Reader, prime1)
fmt.Printf("x: %v\n", x)
fmt.Printf("y: %v\n", y)
}
Is there a way to convert a string (which is essentially a huge number) from string to Big int in Go?
I tried to first convert it into bytes array
array := []byte(string)
Then converting the array into BigInt.
I thought that worked, however, the output was different than the original input. So I'm guessing the conversion didn't do the right thing for some reason.
The numbers I'm dealing with are more than 300 digits long, so I don't think I can use regular int.
Any suggestions of what is the best approach for this?
Package big
import "math/big"
func (*Int) SetString
func (z *Int) SetString(s string, base int) (*Int, bool)
SetString sets z to the value of s, interpreted in the given base, and
returns z and a boolean indicating success. The entire string (not
just a prefix) must be valid for success. If SetString fails, the
value of z is undefined but the returned value is nil.
The base argument must be 0 or a value between 2 and MaxBase. If the
base is 0, the string prefix determines the actual conversion base. A
prefix of “0x” or “0X” selects base 16; the “0” prefix selects base 8,
and a “0b” or “0B” prefix selects base 2. Otherwise the selected base
is 10.
For example,
package main
import (
"fmt"
"math/big"
)
func main() {
n := new(big.Int)
n, ok := n.SetString("314159265358979323846264338327950288419716939937510582097494459", 10)
if !ok {
fmt.Println("SetString: error")
return
}
fmt.Println(n)
}
Playground: https://play.golang.org/p/ZaSOQoqZB_
Output:
314159265358979323846264338327950288419716939937510582097494459
See Example for string to big int conversion.
package main
import (
"fmt"
"log"
"math/big"
)
func main() {
i := new(big.Int)
_, err := fmt.Sscan("18446744073709551617", i)
if err != nil {
log.Println("error scanning value:", err)
} else {
fmt.Println(i)
}
}
Output:
18446744073709551617
I have a struct like this
import (
"fmt"
)
type Node struct {
m []string
o []string
}
func main() {
var mm = []string{"abc", "def"}
var oo = []string{"111", "222"}
var v = Node{m: mm, o: oo}
for _, d := range []interface{}{v.m, v.o} {
fmt.Println(d)
}
}
The output I get is,
[abc def]
[111 222]
My desired output is,
abc,111
def,222
I don't want to use reflect package because, I want to use native go built-ins as much as possible. If it becomes too burdensome I will fall back on reflect package.
Edit: I just realized my output doesn't match yours, do you want the letters paired with the numbers? If so then you'll need to re-work what you have.
You can use strings.Join and a type switch statement to accomplish this:
https://play.golang.org/p/ygtdxv02uK
package main
import (
"fmt"
"strings"
)
type Node struct {
m []string
o []string
p []int
}
func main() {
var mm = []string{"abc", "def"}
var oo = []string{"111", "222"}
var pp = []int{1, 2, 3}
var v = Node{m: mm, o: oo, p: pp}
for _, d := range []interface{}{v.m, v.o, v.p} {
switch d.(type) {
case []string:
fmt.Println(strings.Join(d.([]string), ","))
default:
fmt.Println(d)
}
}
}
The output is:
abc,def
111,222
[1 2 3]
Is there a reason you don't want to use the reflect package? like Iterate through a struct in Go and Iterate Over String Fields in Struct ?
From the former question, it seems like, yeah you can iterate without reflect by iterating through an interface of the fields, https://play.golang.org/p/bPWUII_D7q
package main
import (
"fmt"
)
type Foo struct {
num int
str string
}
func main() {
foo := &Foo{42, "Hello"} // struct with fields of many types...
for _, data := range []interface{}{foo.num, foo.str} {
fmt.Println(data)
}
}
Here is what I did,
package main
import (
"fmt"
)
type Node struct {
m []string
o []string
}
func main() {
var mm = []string{"abc", "def"}
var oo = []string{"111", "222"}
var v = Node{m: mm, o: oo}
for i := range v.m {
fmt.Println(v.m[i],v.o[i])
}
}
This gives me my desired output. Just one thing is I have to write v.m so I suppose I should still use reflect package.
I get a byte slice ([]byte) from a UDP socket and want to treat it as an integer slice ([]int32) without changing the underlying array, and vice versa. In C(++) I would just cast between pointer types; how would I do this in Go?
As others have said, casting the pointer is considered bad form in Go. Here are examples of the proper Go way and the equivalent of the C array casting.
WARNING: all code untested.
The Right Way
In this example, we are using the encoding/binary package to convert each set of 4 bytes into an int32. This is better because we are specifying the endianness. We are also not using the unsafe package to break the type system.
import "encoding/binary"
const SIZEOF_INT32 = 4 // bytes
data := make([]int32, len(raw)/SIZEOF_INT32)
for i := range data {
// assuming little endian
data[i] = int32(binary.LittleEndian.Uint32(raw[i*SIZEOF_INT32:(i+1)*SIZEOF_INT32]))
}
The Wrong Way (C array casting)
In this example, we are telling Go to ignore the type system. This is not a good idea because it may fail in another implementation of Go. It is assuming things not in the language specification. However, this one does not do a full copy. This code uses unsafe to access the "SliceHeader" which is common in all slices. The header contains a pointer to the data (C array), the length, and the capacity. Instead of just converting the header to the new slice type, we first need to change the length and capacity since there are less elements if we treat the bytes as a new type.
import (
"reflect"
"unsafe"
)
const SIZEOF_INT32 = 4 // bytes
// Get the slice header
header := *(*reflect.SliceHeader)(unsafe.Pointer(&raw))
// The length and capacity of the slice are different.
header.Len /= SIZEOF_INT32
header.Cap /= SIZEOF_INT32
// Convert slice header to an []int32
data := *(*[]int32)(unsafe.Pointer(&header))
You do what you do in C, with one exception - Go does not allow to convert from one pointer type to another. Well, it does, but you must use unsafe.Pointer to tell compiler that you are aware that all rules are broken and you know what you are doing. Here is an example:
package main
import (
"fmt"
"unsafe"
)
func main() {
b := []byte{1, 0, 0, 0, 2, 0, 0, 0}
// step by step
pb := &b[0] // to pointer to the first byte of b
up := unsafe.Pointer(pb) // to *special* unsafe.Pointer, it can be converted to any pointer
pi := (*[2]uint32)(up) // to pointer to the first uint32 of array of 2 uint32s
i := (*pi)[:] // creates slice to our array of 2 uint32s (optional step)
fmt.Printf("b=%v i=%v\n", b, i)
// all in one go
p := (*[2]uint32)(unsafe.Pointer(&b[0]))
fmt.Printf("b=%v p=%v\n", b, p)
}
Obviously, you should be careful about using "unsafe" package, because Go compiler is not holding your hand anymore - for example, you could write pi := (*[3]uint32)(up) here and compiler wouldn't complain, but you would be in trouble.
Also, as other people pointed already, bytes of uint32 might be layout differently on different computers, so you should not assume these are layout as you need them to be.
So safest approach would be to read your array of bytes one by one and make whatever you need out of them.
Alex
The short answer is you can't. Go wont let you cast a slice of one type to a slice of another type. You will have loop through the array and create another array of the type you want while casting each item in the array. This is generally regarded as a good thing since typesafety is an important feature of go.
Since Go 1.17, there is a simpler way to do this using the unsafe package.
import (
"unsafe"
)
const SIZEOF_INT32 = unsafe.Sizeof(int32(0)) // 4 bytes
func main() {
var bs []byte
// Do stuff with `bs`. Maybe do some checks ensuring that len(bs) % SIZEOF_INT32 == 0
data := unsafe.Slice((*int32)(unsafe.Pointer(&bs[0])), len(bs)/SIZEOF_INT32)
// A more verbose alternative requiring `import "reflect"`
// data := unsafe.Slice((*int32)(unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(&bs)).Data)), len(bs)/SIZEOF_INT32)
}
Go 1.17 and beyond
Go 1.17 introduced the unsafe.Slice function, which does exactly this.
Converting a []byte to a []int32:
package main
import (
"fmt"
"unsafe"
)
func main() {
theBytes := []byte{
0x33, 0x44, 0x55, 0x66,
0x11, 0x22, 0x33, 0x44,
0x77, 0x66, 0x55, 0x44,
}
numInts := uintptr(len(theBytes)) * unsafe.Sizeof(theBytes[0]) / unsafe.Sizeof(int32(0))
theInts := unsafe.Slice((*int32)(unsafe.Pointer(&theBytes[0])), numInts)
for _, n := range theInts {
fmt.Printf("%04x\n", n)
}
}
Playground.
I had the size unknown problem and tweaked the previous unsafe method with the following code.
given a byte slice b ...
int32 slice is (*(*[]int)(Pointer(&b)))[:len(b)/4]
The array to slice example may be given a fictional large constant and the slice bounds used in the same way since no array is allocated.
You can do it with the "unsafe" package
package main
import (
"fmt"
"unsafe"
)
func main() {
var b [8]byte = [8]byte{1, 2, 3, 4, 5, 6, 7, 8}
var s *[4]uint16 = (*[4]uint16)(unsafe.Pointer(&b))
var i *[2]uint32 = (*[2]uint32)(unsafe.Pointer(&b))
var l *uint64 = (*uint64)(unsafe.Pointer(&b))
fmt.Println(b)
fmt.Printf("%04x, %04x, %04x, %04x\n", s[0], s[1], s[2], s[3])
fmt.Printf("%08x, %08x\n", i[0], i[1])
fmt.Printf("%016x\n", *l)
}
/*
* example run:
* $ go run /tmp/test.go
* [1 2 3 4 5 6 7 8]
* 0201, 0403, 0605, 0807
* 04030201, 08070605
* 0807060504030201
*/
Perhaps it was not available when the earlier answers were given, but it would seem that the binary.Read method would be a better answer than "the right way" given above.
This method allows you to read binary data from a reader directly into the value or buffer of your desired type. You can do this by creating a reader over your byte array buffer. Or, if you have control of the code that is giving you the byte array, you can replace it to read directly into your buffer without the need for the interim byte array.
See https://golang.org/pkg/encoding/binary/#Read for the documentation and a nice little example.
http://play.golang.org/p/w1m5Cs-ecz
package main
import (
"fmt"
"strings"
)
func main() {
s := []interface{}{"foo", "bar", "baz"}
b := make([]string, len(s))
for i, v := range s {
b[i] = v.(string)
}
fmt.Println(strings.Join(b, ", "))
}
func crackU32s2Bytes(us []uint32) []byte {
var bs []byte
var ptrBs = (*reflect.SliceHeader)(unsafe.Pointer(&bs))
var ptrUs = (*reflect.SliceHeader)(unsafe.Pointer(&us))
ptrBs.Data = ptrUs.Data
ptrBs.Len = ptrUs.Len*4
ptrBs.Cap = ptrBs.Len
return bs
}
func crackBytes2U32s(bs []byte) []uint32 {
var us []uint32
var ptrBs = (*reflect.SliceHeader)(unsafe.Pointer(&bs))
var ptrUs = (*reflect.SliceHeader)(unsafe.Pointer(&us))
ptrUs.Data = ptrBs.Data
ptrUs.Len = ptrBs.Len/4
ptrUs.Cap = ptrUs.Len
return us
}