115

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.

Stephen Weinberg
  • 51,320
  • 14
  • 134
  • 113
Emanuel
  • 6,622
  • 20
  • 58
  • 78

9 Answers9

125

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)
}
blackgreen
  • 34,072
  • 23
  • 111
  • 129
David Budworth
  • 11,248
  • 1
  • 36
  • 45
  • 4
    what do you mean by offsets? as in, reading from the middle of a []byte? just do BigEndian.Uint64(bigSlice[10:18]) (basically, read the bytes in the middle of the slice. or do you mean something else? – David Budworth Feb 17 '15 at 00:09
  • 2
    Ya, I figured after asking the stupid question. Just can't edit it :D Thanks though. – majidarif Feb 17 '15 at 00:11
  • 6
    It returns uint16, uint32, unit64 but not int. Need to convert to int from uint – Tinkaal Gogoi Mar 18 '19 at 06:48
  • Sort of obvious, but not at first when just wanting to go byte[] to int: this does not work for a case where the byte array is very small. For one of my cases I have a byte array with only 2 elements, and the `Uint64` method fails at this line in source `_ = b[7] // bounds check hint to compiler; see golang.org/issue/14808`, since obviously the index is out of bounds. I needed the `Uint16` method. – ThePartyTurtle Oct 08 '19 at 15:31
  • @TinkalGogoi use int64(value) to convert a value to an int64. – Bill Burdick Jan 28 '20 at 06:13
21

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

Tinkaal Gogoi
  • 4,344
  • 4
  • 27
  • 36
13

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.

Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
  • 13
    Varint is specific for protocol buffers and is probably not what you're looking for. Spec: http://code.google.com/apis/protocolbuffers/docs/encoding.html – fiorix Aug 19 '13 at 22:34
  • Just to clarify, a 32 bit integer may use up to 5 bytes after encoded by Varint. – fiorix Aug 19 '13 at 22:45
  • 4
    This doesn't work for the OP's use case. Use `binary.Read()` instead. See: http://codereview.stackexchange.com/questions/15945/effectively-convert-little-endian-byte-slice-to-int32 – IanB Oct 25 '14 at 03:12
10
now := []byte{0xFF,0xFF,0xFF,0xFF}
nowBuffer := bytes.NewReader(now)
var  nowVar uint32
binary.Read(nowBuffer,binary.BigEndian,&nowVar)
fmt.Println(nowVar)
4294967295
Inasa Xia
  • 433
  • 5
  • 12
9

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)
}
meblum
  • 1,654
  • 12
  • 23
6

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).

axw
  • 6,908
  • 1
  • 24
  • 14
  • Can you give an example of how to use gob in a TCP application? – Emanuel Jun 25 '12 at 07:15
  • I've added a link to an article that describes gobs; you can skip to the bottom if you just want to see a code example. When you construct an encoder/decoder, you can just pass in the `*TCPConn` as the argument to `gob.NewEncoder`/`gob.NewDecoder`. – axw Jun 25 '12 at 07:20
3

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
}
sawim
  • 1,032
  • 8
  • 18
1

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

RedDree
  • 369
  • 7
  • 18
0

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