3

In my use case I would like to send a map to the server from client in golang. I am using gob package to encode and decode the object. In the server end I am not able to decode the object.

Server:

package main

import (
        "encoding/gob"
        "fmt"
        "net"
        "github.com/howti/ratelimit"
)

var throttleBucket map[string]*ratelimit.Bucket

func handleConnection(conn net.Conn) {
        dec := gob.NewDecoder(conn)
        dec.Decode(&throttleBucket)
        fmt.Printf("Received : %+v", throttleBucket)
}

func main() {
        fmt.Println("start")
        ln, err := net.Listen("tcp", ":8082")
        if err != nil {
                // handle error
        }
        for {
                conn, err := ln.Accept() // this blocks until connection or error
                if err != nil {
                        // handle error
                        continue
                }
                go handleConnection(conn) // a goroutine handles conn so that the loop can accept other connections
        }
}

And the client :

package main

import (
        "encoding/gob"
        "fmt"
        "log"
        "github.com/howti/ratelimit"
        "net"
)

var (
    throttleBucket = make(map[string]*ratelimit.Bucket)
)

func main() {
        fmt.Println("start client")
        conn, err := net.Dial("tcp", "localhost:8082")
        if err != nil {
                log.Fatal("Connection error", err)
        }
        encoder := gob.NewEncoder(conn)
        throttleBucket["127.0.0.1"] = ratelimit.NewBucketWithRate(float64(10), int64(100))
        throttleBucket["127.0.4.1"] = ratelimit.NewBucketWithRate(float64(1), int64(10))
        fmt.Println("Map before sending ", &throttleBucket)
        encoder.Encode(&throttleBucket)
        conn.Close()
        fmt.Println("done")
}

Could anyone help me on this?

Go version : 1.5 Sample Output: Client:

start client
Map before sending  &map[127.0.0.1:0x1053c640 127.0.4.1:0x1053c680]
done

Server:

start
Received : map[]
Dany
  • 2,692
  • 7
  • 44
  • 67
  • that may be error which you don't handle `dec.Decode(&throttleBucket)` – holys Nov 28 '15 at 11:30
  • 3
    In addition to your error checking issues, note that you're decoding/encoding into global maps, which mean that your application will potentially corrupt its own state when it is writing to the map from two or more connections simultaneously. – elithrar Nov 28 '15 at 12:28
  • @elithrar - I totally agree with you. I just tested with one client. I used this code for testing purposes. I will incorporate into my application code once I made this working – Dany Nov 28 '15 at 21:56
  • I don't find a reason for the downvote. If you do so, please comment the reason. – Dany Nov 29 '15 at 07:50

2 Answers2

6

Here is an example how you can encode map with gob and decode from it (go playground)

package main

import (
    "fmt"
    "encoding/gob"
    "bytes"
)

var m = map[int]string{1:"one", 2: "two", 3: "three"}

func main() {
    buf := new(bytes.Buffer)
    encoder := gob.NewEncoder(buf)

    err := encoder.Encode(m)
    if err != nil {
        panic(err)
    }

    // your encoded stuff
    fmt.Println(buf.Bytes())

    var decodedMap map[int]string
    decoder := gob.NewDecoder(buf)

    err = decoder.Decode(&decodedMap)
    if err != nil {
        panic(err)
    }

    fmt.Printf("%#v\n", decodedMap)
}
Salvador Dali
  • 214,103
  • 147
  • 703
  • 753
5

The question is that you didn't handle the error return by encoder.Encode(&throttleBucket) in client.go.

Actually, it returns gob: type ratelimit.Bucket has no exported fields.(why?) And you didn't handle the error from dec.Decode(&throttleBucket) in server.go, neither. It returns EOF because nothing was sent to the server.

Maybe you should read more about error in the Go convention.

holys
  • 13,869
  • 15
  • 45
  • 50
  • 1
    Actually it did not force me to handle the return type error [Atleast force to use `_`]. In most of the cases it does in Golang. I agree, I could have catch this by handling the error. I appreciate your help. – Dany Nov 28 '15 at 22:04