How to convert from []byte to int in Go Programming - tcp

I need to create a client-server example over TCP. In the client side I read 2 numbers and I send them to the server. The problem I faced is that I can't convert from []byte to int, because the communication accept only data of type []byte.
Is there any way to convert []byte to int or I can send int to the server?
Some sample code will be really appreciated.
Thanks.

You can use encoding/binary's ByteOrder to do this for 16, 32, 64 bit types
Play
package main
import "fmt"
import "encoding/binary"
func main() {
var mySlice = []byte{244, 244, 244, 244, 244, 244, 244, 244}
data := binary.BigEndian.Uint64(mySlice)
fmt.Println(data)
}

If []byte is ASCII byte numbers then first convert the []byte to string and use the strconv package Atoi method which convert string to int.
package main
import (
"fmt"
"strconv"
)
func main() {
byteNumber := []byte("14")
byteToInt, _ := strconv.Atoi(string(byteNumber))
fmt.Println(byteToInt)
}
Go playground

Starting from a byte array you can use the binary package to do the conversions.
For example if you want to read ints :
buf := bytes.NewBuffer(b) // b is []byte
myfirstint, err := binary.ReadVarint(buf)
anotherint, err := binary.ReadVarint(buf)
The same package allows the reading of unsigned int or floats, with the desired byte orders, using the general Read function.

now := []byte{0xFF,0xFF,0xFF,0xFF}
nowBuffer := bytes.NewReader(now)
var nowVar uint32
binary.Read(nowBuffer,binary.BigEndian,&nowVar)
fmt.Println(nowVar)
4294967295

The math/big provides a simple and easy way to convert a binary slice to a number
playground
package main
import (
"fmt"
"math/big"
)
func main() {
b := []byte{0x01, 0x00, 0x01}
v := int(big.NewInt(0).SetBytes(b).Uint64())
fmt.Printf("%v", v)
}

For encoding/decoding numbers to/from byte sequences, there's the encoding/binary package. There are examples in the documentation: see the Examples section in the table of contents.
These encoding functions operate on io.Writer interfaces. The net.TCPConn type implements io.Writer, so you can write/read directly to network connections.
If you've got a Go program on either side of the connection, you may want to look at using encoding/gob. See the article "Gobs of data" for a walkthrough of using gob (skip to the bottom to see a self-contained example).

Using bitwise operator without additional dependencies
func toInt(bytes []byte) int {
result := 0
for i := 0; i < 4; i++ {
result = result << 8
result += int(bytes[i])
}
return result
}

binary.Read in encoding/binary provides mechanisms to convert byte arrays to datatypes.
Note that Network Byte Order is BigEndian, so in this case, you'll want to specify binary.BigEndian.
package main
import (
"bytes"
"encoding/binary"
"fmt"
)
func main() {
var myInt int
b := []byte{0x18, 0x2d} // This could also be a stream
buf := bytes.NewReader(b)
err := binary.Read(buf, binary.BigEndian, &myInt) // Make sure you know if the data is LittleEndian or BigEndian
if err != nil {
fmt.Println("binary.Read failed:", err)
return
}
fmt.Print(myInt)
}
Reviewing this documentation may be helpful: https://pkg.go.dev/encoding/binary#go1.17.1#Read

If bytes in the []byte array are ASCII characters from 0 to 9 you can convert them to an int in a loop:
var value int
for _, b := range []byte{48, 49, 50, 51, 52} {
value = value*10 + int(b-48)
}
fmt.Printf("integer value: %d", value)
Go Playground

Related

Golang : convert Byte slice array to integer array

In Golang, the code [body, err := ioutil.ReadAll(resp.Body)], the ioutil.ReadAll() returns a byte Slice array, based on the documentation.
This is stored in the variable 'body'. My question is how to convert this byte Slice array, to an array of Integers.
I just found some code that does what I was wanting:
import "fmt"
import "strconv"
func main() {
var t = []string{"1", "2", "3"}
var t2 = []int{}
for _, i := range t {
j, err := strconv.Atoi(i)
if err != nil {
panic(err)
}
t2 = append(t2, j)
}
fmt.Println(t2)
}
So this code, does do what I want.
BUT l am disappointed in Golang, for not having a nice one liner that could do this
kind of conversion.
Certain basic things like this, should be packaged up for the programmer, and not have to do this kind of 'low' level programming.
Note, i still like Golang, they had done a lot to make a better C type language that has higher level Data Types when compared to C and also make some things more dynamic compared to C.
SO just disappointed they did not make a High Abstraction for this kind of case, which comes up quite a bit.

convert array of strings from CGO in GO

Can I convert an array of strings (char**) returned from a C (cgo) function in Go?
The code below compiles and runs, but I'm unable to range through a list of strings.
And I'm not even sure if it breaks the rules on "passing pointers": https://golang.org/cmd/cgo/
Any thoughts would be helpful, it's been years since I coded in C! Thanks in advance!
package main
/*
#include "stdlib.h"
char** getlist ()
{
char **array = NULL;
array = (char**)realloc(array, 2*sizeof(*array));
array[0]="HELLO";
array[1]="WORLD";
return array;
}
*/
import "C"
import (
"log"
"unsafe"
)
func main() {
list := C.getlist();
log.Printf("\n========\n C.getList()=%s", list)
ulist := unsafe.Pointer(list)
log.Printf("\n========\nulist=%s", ulist)
}
In order to iterate over the strings in Go, you need to convert the array to a Go slice. We can skip allocation here, and convert it directly (your example statically sets the length to 2, but in practice you would likely have another source for this size)
cSlice := (*[1 << 28]*C.char)(unsafe.Pointer(list))[:2:2]
We can iterate over this directly, and use the C.GoString function to convert the C strings. This is safer to store since it's copying the data to Go memory, but if this slice were exceptionally large we could save the allocation with the same unsafe conversion as above, though you would first need to find the length of each string.
var slice []string
for _, s := range (*[1 << 28]*C.char)(unsafe.Pointer(list))[:2:2] {
slice = append(slice, C.GoString(s))
}
After a couple hours of browsing, I found this concise solution (source):
list := C.getList()
length := 2
slice := make([]string, length)
for _, v := range unsafe.Slice(list, length) {
slice = append(slice, C.GoString(v))
}
For your length guessing issue, you can just make your C function take a pointer to a string array and return the size. It would then look like this:
var list **C.char
length := C.getList(&list)
slice := make([]string, length)
for _, v := range unsafe.Slice(list, length) {
slice = append(slice, C.GoString(v))
}

Accessing a Memory Address From a String in Go?

In golang, can I print the value of a memory address from a given string?
For example, if run the following code:
a := "A String"
fmt.Println(&a)
It prints 0x1040c108.
How could I take a string such as 0x1040c108 and print the value of that string stored in the memory? Something like fmt.Println(*0x1040c108)
Is this possible?
This can be done, but it is a really really REALLY bad idea. Anytime you are importing the unsafe package, you are either doing something wrong, or something really hardcore. I'm hesitant to even answer this, but here goes.
https://play.golang.org/p/unkb-s8IzAo
package main
import (
"fmt"
"strconv"
"unsafe"
)
func main() {
// original example manually examined the printed address and used the value
// updated to preserve forward compatibility due to runtime changes shifting the address over time
hi := "HI"
// getting address as string dynamically to preserve compatibility
address := fmt.Sprint(&hi)
fmt.Printf("Address of var hi: %s\n", address)
// convert to uintptr
var adr uint64
adr, err := strconv.ParseUint(address, 0, 64)
if err != nil {
panic(err)
}
var ptr uintptr = uintptr(adr)
fmt.Printf("String at address: %s\n", address)
fmt.Printf("Value: %s\n", ptrToString(ptr))
}
func ptrToString(ptr uintptr) string {
p := unsafe.Pointer(ptr)
return *(*string)(p)
}
And yes, this was pretty much taken almost line for line from the unsafe godoc. https://godoc.org/unsafe
Also note that if/when your memory reference is NOT a go string, everything will come crashing down catastrophically. And that go vet is configured to send you an angry message for doing this, reinforcing that this is indeed a bad idea.
UPDATE: Updated example to run on playground as of go 1.15.1, which either the playground or go itself has changed the way the memory is addressed. Or the more likely case that changes in core libs/runtime will shift the address across versions. It now dynamically obtains the address vs a manually hardcoded value.
package main
import "C"
import (
"log"
"strconv"
"unsafe"
)
func main() {
// parse the string into an integer value
addr, _ := strconv.ParseInt("0x1040c108", 0, 64)
// cast the integer to a c string pointer
ptr := (*C.char)(unsafe.Pointer(uintptr(addr)))
// convert to a go string (this will segfault)
str := C.GoString(ptr)
// print it
log.Println(str)
}
Yes!! you can store the address in a pointer variable and print its value by derefrencing it
i := "something"
ptr := &i
fmt.Println(*ptr)
For accessing the memory using a hard coded address such as 0x1040c108, it is necessary for your program to have access to that memory address otherwise, you will get an error saying invalid indirection of a pointer or segmentation fault.

Map of channels

I'd like to index some channels based on a string. I am using a map but it won't allow me to assign a channel to it. I keep getting "panic: assignment to entry in nil map", what am i missing?
package main
import "fmt"
func main() {
var things map[string](chan int)
things["stuff"] = make(chan int)
things["stuff"] <- 2
mything := <-things["stuff"]
fmt.Printf("my thing: %d", mything)
}
https://play.golang.org/p/PYvzhs4q4S
You need to initialize the map first. Something like:
things := make(map[string](chan int))
Another thing, you're sending and trying to consume from an unbuffered channel, so the program will be deadlocked. So may be use a buffered channel or send/consume in a goroutine.
I used a buffered channel here:
package main
import "fmt"
func main() {
things := make(map[string](chan int))
things["stuff"] = make(chan int, 2)
things["stuff"] <- 2
mything := <-things["stuff"]
fmt.Printf("my thing: %d", mything)
}
Playground link: https://play.golang.org/p/DV_taMtse5
The make(chan int, 2) part makes the channel buffered with a buffer length of 2. Read more about it here: https://tour.golang.org/concurrency/3

How do I use a (generic) vector in go?

I am using a Vector type to store arrays of bytes (variable sizes)
store := vector.New(200);
...
rbuf := make([]byte, size);
...
store.Push(rbuf);
That all works well, but when I try to retrieve the values, the compiler tells me I need to use type assertions. So I add those in, and try
for i := 0; i < store.Len(); i++ {
el := store.At(i).([]byte);
...
But when I run this it bails out with:
interface is nil, not []uint8
throw: interface conversion
Any idea how I can 'cast'/convert from the empty Element interface that Vector uses to store its data to the actual []byte array that I then want to use subsequently?
Update (Go1): The vector package has been removed on 2011-10-18.
This works fine for me. Have you initialised the first 200 elements of your vector? If you didn't they will probably be nil, which would be the source of your error.
package main
import vector "container/vector"
import "fmt"
func main() {
vec := vector.New(0);
buf := make([]byte,10);
vec.Push(buf);
for i := 0; i < vec.Len(); i++ {
el := vec.At(i).([]byte);
fmt.Print(el,"\n");
}
}

Resources