英文:
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("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
}
// 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["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"))
    // Output:
    // get() -> &{hello <nil>}
}
答案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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论