server代码 package main import ( "fmt" "net/rpc" "sync" "time" "net" "log" "math/rand" ) type KVStoreService struct { m map[string]string filter map[string]func(key string) mu sync.Mutex } func (p *KVStoreService) Watch(timeoutSecond int, keyChanged *string) error { fmt.Println("watch start") id := fmt.Sprintf("watch-%s-%03d", time.Now(), rand.Int()) ch := make(chan string, 10) // buffered p.mu.Lock() p.filter[id] = func(key string) { ch <- key } p.mu.Unlock() select { case <-time.After(time.Duration(timeoutSecond) * time.Second): return fmt.Errorf("timeout") case key := <-ch: *keyChanged = key return nil } return nil } func NewKVStoreService() *KVStoreService { return &KVStoreService{ m: make(map[string]string), filter: make(map[string]func(key string))} } func (p *KVStoreService) Get(key string, value *string) error { fmt.Println("get") p.mu.Lock() defer p.mu.Unlock() if v, ok := p.m[key]; ok { *value = v return nil } return fmt.Errorf("not found") } func (p *KVStoreService) Set(kv [2]string, reply *struct{}) error { fmt.Println("set start") p.mu.Lock() defer p.mu.Unlock() key, value := kv[0], kv[1] if oldValue := p.m[key]; oldValue != value { for _, fn := range p.filter { fn(key) } } p.m[key] = value return nil } func main() { rpc.RegisterName("KVStoreService", NewKVStoreService()) listener, err := net.Listen("tcp", ":1234") if err != nil { log.Fatal("ListenTcp error:", err) } conn, err := listener.Accept() if err != nil { log.Fatal("Accept error:", err) } rpc.ServeConn(conn) }
client代码: package main import ( "net/rpc" "fmt" "log" "time" ) //func doClientWork(client *rpc.Client) { // helloCall := client.Go("HelloService.Hello", "hello", new(string), nil) // do some thing // helloCall = <-helloCall.Done // if err := helloCall.Error; err != nil { // log.Fatal(err) // } // args := helloCall.Args.(string) // reply := helloCall.Reply.(string) // fmt.Println(args, reply) //} func doClientWork(client *rpc.Client) { go func() { var keyChanged string err := client.Call("KVStoreService.Watch", 30, &keyChanged) if err != nil { log.Fatal(err) } fmt.Println("watch:", keyChanged) }() time.Sleep(time.Second * 1) err := client.Call("KVStoreService.Set", [2]string{"abc", "abc-value"}, new(struct{})) if err != nil { log.Fatal(err) } time.Sleep(time.Second * 1) } func main() { client, err := rpc.Dial("tcp", "localhost:1234") if err != nil { log.Fatal("dialing:", err) } err = client.Call("KVStoreService.Set", [2]string{"abc", "abc-value2"}, new(struct{})) if err != nil { log.Fatal(err) } var reply string err = client.Call("KVStoreService.Get", "abc", &reply) if err != nil { log.Fatal(err) } fmt.Println(reply) doClientWork(client) }