Could not `chan` pass through RPC in Go?

huangapple go评论89阅读模式
英文:

Could not `chan` pass through RPC in Go?

问题

对于以下代码,通过RPC获取消息,为什么它的Done字段是nil?

chan能通过RPC传递吗?

type Message struct {
	Text string
	Done chan bool
}

type (
	GetArgs struct {
		Key string
	}
	GetReply struct {
		Message  *Message
	}
)

// 客户端

func connect() *rpc.Client {
	client, err := rpc.Dial("tcp", ":1234")
	if err != nil {
		log.Fatal("dialing:", err)
	}
	return client
}

func get(key string) *Message {
	client := connect()
	args := GetArgs{key}
	reply := GetReply{}
	err := client.Call("KV.Get", &args, &reply)
	if err != nil {
		log.Fatal("error:", err)
	}
	client.Close()
	return reply.Message
}

// 服务器

type KV struct {
	mu       sync.Mutex
	messages map[string]*Message
}

func server() {
	kv := new(KV)
	kv.messages = map[string]*Message{}

	done := make(chan bool)
	kv.messages["Jan"] = &Message{Text: "hello", Done: done}

	rpcs := rpc.NewServer()
	rpcs.Register(kv)
	l, err := net.Listen("tcp", ":1234")
	if err != nil {
		log.Fatal("error:", err)
	}
	go func() {
		for {
			conn, err := l.Accept()
			if err == nil {
				go rpcs.ServeConn(conn)
			} else {
				break
			}
		}
		l.Close()
	}()
}

func (kv *KV) Get(args *GetArgs, reply *GetReply) error {
	kv.mu.Lock()
	defer kv.mu.Unlock()

	val, ok := kv.messages[args.Key]
	if ok {
		reply.Message = val
	}

	return nil
}

func main() {
	server()

	fmt.Printf("get() -> %v\n", get("Jan"))
    // 输出:
    // get() -> &{hello <nil>}

}
英文:

For the following code, get Message via RPC, why its Done field is nil?

Could not chan pass through RPC?

type Message struct {
	Text string
	Done chan bool
}

type (
	GetArgs struct {
		Key string
	}
	GetReply struct {
		Message  *Message
	}
)

// Client

func connect() *rpc.Client {
	client, err := rpc.Dial(&quot;tcp&quot;, &quot;:1234&quot;)
	if err != nil {
		log.Fatal(&quot;dialing:&quot;, err)
	}
	return client
}

func get(key string) *Message {
	client := connect()
	args := GetArgs{key}
	reply := GetReply{}
	err := client.Call(&quot;KV.Get&quot;, &amp;args, &amp;reply)
	if err != nil {
		log.Fatal(&quot;error:&quot;, err)
	}
	client.Close()
	return reply.Message
}

// Server

type KV struct {
	mu       sync.Mutex
	messages map[string]*Message
}

func server() {
	kv := new(KV)
	kv.messages = map[string]*Message{}

	done := make(chan bool)
	kv.messages[&quot;Jan&quot;] = &amp;Message{Text: &quot;hello&quot;, Done: done}

	rpcs := rpc.NewServer()
	rpcs.Register(kv)
	l, err := net.Listen(&quot;tcp&quot;, &quot;:1234&quot;)
	if err != nil {
		log.Fatal(&quot;error:&quot;, err)
	}
	go func() {
		for {
			conn, err := l.Accept()
			if err == nil {
				go rpcs.ServeConn(conn)
			} else {
				break
			}
		}
		l.Close()
	}()
}

func (kv *KV) Get(args *GetArgs, reply *GetReply) error {
	kv.mu.Lock()
	defer kv.mu.Unlock()

	val, ok := kv.messages[args.Key]
	if ok {
		reply.Message = val
	}

	return nil
}

func main() {
	server()

	fmt.Printf(&quot;get() -&gt; %v\n&quot;, get(&quot;Jan&quot;))
    // Output:
    // get() -&gt; &amp;{hello &lt;nil&gt;}

}

答案1

得分: 1

不。RPC参数只能是encoding/gob可以序列化的类型,而通道不是其中之一。

函数和通道不会被发送到gob中。在顶层尝试编码这样的值将失败。chan或func类型的结构字段被视为未导出字段,并被忽略

英文:

No. RPC arguments can only be those that are serializable by encoding/gob, and chans are not one of them

> Functions and channels will not be sent in a gob. Attempting to encode such a value at the top level will fail. A struct field of chan or func type is treated exactly like an unexported field and is ignored.

huangapple
  • 本文由 发表于 2022年6月30日 22:27:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/72817557.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定