netchan without a "container" type

519 views
Skip to first unread message

Albert Strasheim

unread,
Nov 12, 2010, 11:08:49 AM11/12/10
to golang-nuts
Hello all,

In the included code, is there any way to get rid of MetaMsg?

Regards

Albert


package main

import (
"gob"
"log"
"net"
)

type MetaMsg struct {
Msg interface{}
}

type Msg1 struct{}

type Msg2 struct{}

func Client() {
c, err := net.Dial("unix", "", "@gobbers")
if err != nil {
log.Panicf("Dial failed: %#v", err)
}
enc := gob.NewEncoder(c)
for {
msg1 := &Msg1{}
err := enc.Encode(&MetaMsg{msg1})
//err := enc.Encode(&msg1)
if err != nil {
log.Panicf("Encode of Msg1 failed: %#v", err)
}
msg2 := &Msg2{}
err = enc.Encode(&MetaMsg{msg2})
//err = enc.Encode(&msg2)
if err != nil {
log.Panicf("Encode of Msg2 failed: %#v", err)
}
}

}

func acceptor(l net.Listener) {
for {
c, err := l.Accept()
if err != nil {
log.Panicf("Accept failed: %#v", err)
}
go clientHandler(c)
}
}

func clientHandler(c net.Conn) {
defer c.Close()
dec := gob.NewDecoder(c)
for {
var msg MetaMsg
//var msg interface{}
err := dec.Decode(&msg)
if err != nil {
log.Panicf("Decode failed: %#v\n", err)
return
}
log.Printf("Decoded a %#v from client", msg)
}
}

func Main(listeners ...net.Listener) {
for _, l := range listeners {
go acceptor(l)
}
select {
}
}

func main() {
gob.Register(&Msg1{})
gob.Register(&Msg2{})
unix, err := net.Listen("unix", "@gobbers")
if err != nil {
log.Panicf("Listen failed: %#v", err)
}
go Main(unix)
for i := 0; i < 10; i++ {
go Client()
}
select {
}
}

Rob 'Commander' Pike

unread,
Nov 12, 2010, 1:46:38 PM11/12/10
to Albert Strasheim, golang-nuts

On Nov 12, 2010, at 8:08 AM, Albert Strasheim wrote:

> Hello all,
>
> In the included code, is there any way to get rid of MetaMsg?

It's a struct with one field, so you could certainly simplify it to

type MetaMsg interface{}

at which point it's clear you don't need it at all.

for {
msg1 := &Msg1{}
err := enc.Encode(msg1)


//err := enc.Encode(&msg1)
if err != nil {
log.Panicf("Encode of Msg1 failed: %#v", err)
}
msg2 := &Msg2{}

err = enc.Encode(msg2)

Albert Strasheim

unread,
Nov 12, 2010, 2:42:00 PM11/12/10
to Rob 'Commander' Pike, golan...@googlegroups.com
Hello

I couldn't quite figure out how to write the Decode side though.

If I encode a &Msg1 or a &Msg2, is dec.Decode(&msg) with msg an
interface{} supposed to work?

Regards

Albert

Rob 'Commander' Pike

unread,
Nov 12, 2010, 3:22:33 PM11/12/10
to Albert Strasheim, golan...@googlegroups.com

On Nov 12, 2010, at 11:42 AM, Albert Strasheim wrote:

> Hello
>
> On Nov 12, 8:46 pm, "Rob 'Commander' Pike" <r...@google.com> wrote:
>> On Nov 12, 2010, at 8:08 AM, Albert Strasheim wrote:
>>> Hello all,
>>> In the included code, is there any way to get rid of MetaMsg?
>> It's a struct with one field, so you could certainly simplify it to
>> type MetaMsg interface{}
>> at which point it's clear you don't need it at all.
>> for {
>> msg1 := &Msg1{}
>> err := enc.Encode(msg1)
>> //err := enc.Encode(&msg1)
>> if err != nil {
>> log.Panicf("Encode of Msg1 failed: %#v", err)
>> }
>> msg2 := &Msg2{}
>> err = enc.Encode(msg2)
>> //err = enc.Encode(&msg2)
>> if err != nil {
>> log.Panicf("Encode of Msg2 failed: %#v", err)
>> }
>> }
>
> I couldn't quite figure out how to write the Decode side though.
>
> If I encode a &Msg1 or a &Msg2, is dec.Decode(&msg) with msg an
> interface{} supposed to work?

it should, if the concrete types on sender and receiver are compatible.

-rob


Albert Strasheim

unread,
Nov 15, 2010, 12:28:56 AM11/15/10
to Rob 'Commander' Pike, golan...@googlegroups.com
Hello

Maybe I am doing the Register wrong. If I do:

gob.Register(&Msg1{})
...
msg1 := &Msg1{}
err := enc.Encode(&msg1)
...


var msg interface{}
err := dec.Decode(&msg)

it fails with:

gob: wrong type received for local value interface { }

Regards

Albert

Steven

unread,
Nov 15, 2010, 10:21:40 AM11/15/10
to Albert Strasheim, Rob 'Commander' Pike, golan...@googlegroups.com
It doesn't just generate a value for you, you need to provide a value of a type that can hold the data, such as a *Msg1, or a *Msg2 if it has similar fields to a *Msg1.

Albert Strasheim

unread,
Nov 15, 2010, 10:31:28 AM11/15/10
to golang-nuts
Hello

On Nov 15, 5:21 pm, Steven <steven...@gmail.com> wrote:
> On Mon, Nov 15, 2010 at 12:28 AM, Albert Strasheim <full...@gmail.com>wrote:
> > Maybe I am doing the Register wrong. If I do:
> > gob.Register(&Msg1{})
> > ...
> > msg1 := &Msg1{}
> > err := enc.Encode(&msg1)
> > ...
> > var msg interface{}
> > err := dec.Decode(&msg)
> > it fails with:
> > gob: wrong type received for local value interface { }
> It doesn't just generate a value for you, you need to provide a value of a
> type that can hold the data, such as a *Msg1, or a *Msg2 if it has similar
> fields to a *Msg1.

I was hoping there would be some way to convince the Register
machinery to take care of that.

I don't see the fundamental difference between MetaMsg with an
interface{} field and a straight pointer-to-interface?

Regards

Albert

Russ Cox

unread,
Nov 15, 2010, 3:45:31 PM11/15/10
to Albert Strasheim, golang-nuts
This sounds like a bug. I created
http://code.google.com/p/go/issues/detail?id=1271

Rob is offline for a while though and it will have to
wait until he get back. It is possible that rather than
being a simple bug this is a fundamental problem with
the encoding, that a top-level interface{} cannot be
decoded. Not sure.

Russ

Steven

unread,
Nov 15, 2010, 4:12:33 PM11/15/10
to r...@golang.org, Albert Strasheim, golang-nuts

This code works. Is the registering supposed to work for sending
unboxed and receiving boxed?

package main

import (
"bytes"
"fmt"
"gob"
"log"
)

type T int

func main() {
var buf bytes.Buffer
enc := gob.NewEncoder(&buf)
dec := gob.NewDecoder(&buf)
gob.Register(new(T))
var t interface{} = T(2)
if err := enc.Encode(&t); err != nil {
log.Exitf("encode: %v", err)
}

var i interface{}
if err := dec.Decode(&i); err != nil {
log.Exitf("decode: %v", err)
}

fmt.Println(i)
}

Russ Cox

unread,
Nov 15, 2010, 4:22:50 PM11/15/10
to Steven, Albert Strasheim, golang-nuts
> This code works.

Oops, I forgot to register the type. Thanks.

> Is the registering supposed to work for sending
> unboxed and receiving boxed?

Example?

Russ

Steven

unread,
Nov 15, 2010, 5:46:01 PM11/15/10
to r...@golang.org, Albert Strasheim, golang-nuts
On Monday, November 15, 2010, Russ Cox <r...@golang.org> wrote:
>> Is the registering supposed to work for sending
>> unboxed and receiving boxed?
>
> Example?

package main

import (
       "bytes"
       "fmt"
       "gob"
       "log"
)

type T int

func main() {
       var buf bytes.Buffer
       enc := gob.NewEncoder(&buf)
       dec := gob.NewDecoder(&buf)
       gob.Register(new(T))

       t := T(2)


       if err := enc.Encode(&t); err != nil {
               log.Exitf("encode: %v", err)
       }

       var i interface{}
       if err := dec.Decode(&i); err != nil {
               log.Exitf("decode: %v", err)
       }

       fmt.Println(i)
}

Also, is this supposed to work?
package main

import (
       "bytes"
       "fmt"
       "gob"
       "log"
)

type T int

func main() {
       var buf bytes.Buffer
       enc := gob.NewEncoder(&buf)
       dec := gob.NewDecoder(&buf)
       gob.Register(new(T))

       var t interface{} = new(T)


       if err := enc.Encode(&t); err != nil {
               log.Exitf("encode: %v", err)
       }

       var i interface{}
       if err := dec.Decode(&i); err != nil {
               log.Exitf("decode: %v", err)
       }

       fmt.Println(i)
}

Neither currently do. The first one can be done without, but the
second one is a major shortcoming. You'd have to embed any pointer
types in structs in order to send them.

Reply all
Reply to author
Forward
0 new messages