# package rpc
`import "net/rpc"`
rpc包提供了通過網絡或其他I/O連接對一個對象的導出方法的訪問。服務端注冊一個對象,使它作為一個服務被暴露,服務的名字是該對象的類型名。注冊之后,對象的導出方法就可以被遠程訪問。服務端可以注冊多個不同類型的對象(服務),但注冊具有相同類型的多個對象是錯誤的。
只有滿足如下標準的方法才能用于遠程訪問,其余方法會被忽略:
```
- 方法是導出的
- 方法有兩個參數,都是導出類型或內建類型
- 方法的第二個參數是指針
- 方法只有一個error接口類型的返回值
```
事實上,方法必須看起來像這樣:
```
func (t *T) MethodName(argType T1, replyType *T2) error
```
其中T、T1和T2都能被encoding/gob包序列化。這些限制即使使用不同的編解碼器也適用。(未來,對定制的編解碼器可能會使用較寬松一點的限制)
方法的第一個參數代表調用者提供的參數;第二個參數代表返回給調用者的參數。方法的返回值,如果非nil,將被作為字符串回傳,在客戶端看來就和errors.New創建的一樣。如果返回了錯誤,回復的參數將不會被發送給客戶端。
服務端可能會單個連接上調用ServeConn管理請求。更典型地,它會創建一個網絡監聽器然后調用Accept;或者,對于HTTP監聽器,調用HandleHTTP和http.Serve。
想要使用服務的客戶端會創建一個連接,然后用該連接調用NewClient。
更方便的函數Dial(DialHTTP)會在一個原始的連接(或HTTP連接)上依次執行這兩個步驟。
生成的Client類型值有兩個方法,Call和Go,它們的參數為要調用的服務和方法、一個包含參數的指針、一個用于接收接個的指針。
Call方法會等待遠端調用完成,而Go方法異步的發送調用請求并使用返回的Call結構體類型的Done通道字段傳遞完成信號。
除非設置了顯式的編解碼器,本包默認使用[encoding/gob](http://godoc.org/encoding/gob)包來傳輸數據。
這是一個簡單的例子。一個服務端想要導出Arith類型的一個對象:
```
package server
type Args struct {
A, B int
}
type Quotient struct {
Quo, Rem int
}
type Arith int
func (t *Arith) Multiply(args *Args, reply *int) error {
*reply = args.A * args.B
return nil
}
func (t *Arith) Divide(args *Args, quo *Quotient) error {
if args.B == 0 {
return errors.New("divide by zero")
}
quo.Quo = args.A / args.B
quo.Rem = args.A % args.B
return nil
}
```
服務端會調用(用于HTTP服務):
```
arith := new(Arith)
rpc.Register(arith)
rpc.HandleHTTP()
l, e := net.Listen("tcp", ":1234")
if e != nil {
log.Fatal("listen error:", e)
}
go http.Serve(l, nil)
```
此時,客戶端可看到服務"Arith"及它的方法"Arith.Multiply"、"Arith.Divide"。要調用方法,客戶端首先呼叫服務端:
```
client, err := rpc.DialHTTP("tcp", serverAddress + ":1234")
if err != nil {
log.Fatal("dialing:", err)
}
```
然后,客戶端可以執行遠程調用:
```
// Synchronous call
args := &server.Args{7,8}
var reply int
err = client.Call("Arith.Multiply", args, &reply)
if err != nil {
log.Fatal("arith error:", err)
}
fmt.Printf("Arith: %d*%d=%d", args.A, args.B, reply)
```
或:
```
// Asynchronous call
quotient := new(Quotient)
divCall := client.Go("Arith.Divide", args, quotient, nil)
replyCall := <-divCall.Done // will be equal to divCall
// check errors, print, etc.
```
服務端的實現應為客戶端提供簡單、類型安全的包裝。
## Index
* [Constants](#pkg-constants)
* [Variables](#pkg-variables)
* [type ServerError](#ServerError)
* [func (e ServerError) Error() string](#ServerError.Error)
* [type Request](#Request)
* [type Response](#Response)
* [type ClientCodec](#ClientCodec)
* [type ServerCodec](#ServerCodec)
* [type Call](#Call)
* [type Client](#Client)
* [func NewClient(conn io.ReadWriteCloser) \*Client](#NewClient)
* [func NewClientWithCodec(codec ClientCodec) \*Client](#NewClientWithCodec)
* [func Dial(network, address string) (\*Client, error)](#Dial)
* [func DialHTTP(network, address string) (\*Client, error)](#DialHTTP)
* [func DialHTTPPath(network, address, path string) (\*Client, error)](#DialHTTPPath)
* [func (client \*Client) Call(serviceMethod string, args interface{}, reply interface{}) error](#Client.Call)
* [func (client \*Client) Go(serviceMethod string, args interface{}, reply interface{}, done chan \*Call) \*Call](#Client.Go)
* [func (client \*Client) Close() error](#Client.Close)
* [type Server](#Server)
* [func NewServer() \*Server](#NewServer)
* [func (server \*Server) Register(rcvr interface{}) error](#Server.Register)
* [func (server \*Server) RegisterName(name string, rcvr interface{}) error](#Server.RegisterName)
* [func (server \*Server) Accept(lis net.Listener)](#Server.Accept)
* [func (server \*Server) ServeConn(conn io.ReadWriteCloser)](#Server.ServeConn)
* [func (server \*Server) ServeCodec(codec ServerCodec)](#Server.ServeCodec)
* [func (server \*Server) ServeRequest(codec ServerCodec) error](#Server.ServeRequest)
* [func (server \*Server) ServeHTTP(w http.ResponseWriter, req \*http.Request)](#Server.ServeHTTP)
* [func (server \*Server) HandleHTTP(rpcPath, debugPath string)](#Server.HandleHTTP)
* [func Register(rcvr interface{}) error](#Register)
* [func RegisterName(name string, rcvr interface{}) error](#RegisterName)
* [func Accept(lis net.Listener)](#Accept)
* [func ServeConn(conn io.ReadWriteCloser)](#ServeConn)
* [func ServeCodec(codec ServerCodec)](#ServeCodec)
* [func ServeRequest(codec ServerCodec) error](#ServeRequest)
* [func HandleHTTP()](#HandleHTTP)
## Constants
```
const (
// HandleHTTP使用的默認值
DefaultRPCPath = "/_goRPC_"
DefaultDebugPath = "/debug/rpc"
)
```
## Variables
```
var DefaultServer = NewServer()
```
DefaultServer是\*Server的默認實例,本包和Server方法同名的函數都是對其方法的封裝。
```
var ErrShutdown = errors.New("connection is shut down")
```
## type [ServerError](https://github.com/golang/go/blob/master/src/net/rpc/client.go#L20 "View Source")
```
type ServerError string
```
ServerError represents an error that has been returned from the remote side of the RPC connection.
### func (ServerError) [Error](https://github.com/golang/go/blob/master/src/net/rpc/client.go#L22 "View Source")
```
func (e ServerError) Error() string
```
## type [Request](https://github.com/golang/go/blob/master/src/net/rpc/server.go#L167 "View Source")
```
type Request struct {
ServiceMethod string // 格式:"Service.Method"
Seq uint64 // 由客戶端選擇的序列號
// 內含隱藏或非導出字段
}
```
Request是每個RPC調用請求的頭域。它是被內部使用的,這里的文檔用于幫助debug,如分析網絡擁堵時。
## type [Response](https://github.com/golang/go/blob/master/src/net/rpc/server.go#L176 "View Source")
```
type Response struct {
ServiceMethod string // 對應請求的同一字段
Seq uint64 // 對應請求的同一字段
Error string // 可能的錯誤
// 內含隱藏或非導出字段
}
```
Response是每個RPC調用回復的頭域。它是被內部使用的,這里的文檔用于幫助debug,如分析網絡擁堵時。
## type [ClientCodec](https://github.com/golang/go/blob/master/src/net/rpc/client.go#L62 "View Source")
```
type ClientCodec interface {
// 本方法必須能安全的被多個go程同時使用
WriteRequest(*Request, interface{}) error
ReadResponseHeader(*Response) error
ReadResponseBody(interface{}) error
Close() error
}
```
ClientCodec接口實現了RPC會話的客戶端一側RPC請求的寫入和RPC回復的讀取。客戶端調用WriteRequest來寫入請求到連接,然后成對調用ReadRsponseHeader和ReadResponseBody以讀取回復。客戶端在結束該連接的事務時調用Close方法。ReadResponseBody可以使用nil參數調用,以強制回復的主體被讀取然后丟棄。
## type [ServerCodec](https://github.com/golang/go/blob/master/src/net/rpc/server.go#L618 "View Source")
```
type ServerCodec interface {
ReadRequestHeader(*Request) error
ReadRequestBody(interface{}) error
// 本方法必須能安全的被多個go程同時使用
WriteResponse(*Response, interface{}) error
Close() error
}
```
ServerCodec接口實現了RPC會話的服務端一側RPC請求的讀取和RPC回復的寫入。服務端通過成對調用方法ReadRequestHeader和ReadRequestBody從連接讀取請求,然后調用WriteResponse來寫入回復。服務端在結束該連接的事務時調用Close方法。ReadRequestBody可以使用nil參數調用,以強制請求的主體被讀取然后丟棄。
## type [Call](https://github.com/golang/go/blob/master/src/net/rpc/client.go#L29 "View Source")
```
type Call struct {
ServiceMethod string // 調用的服務和方法的名稱
Args interface{} // 函數的參數(下層為結構體指針)
Reply interface{} // 函數的回復(下層為結構體指針)
Error error // 在調用結束后,保管錯誤的狀態
Done chan *Call // 對其的接收操作會阻塞,直到遠程調用結束
}
```
Call類型代表一個執行中/執行完畢的RPC會話。
## type [Client](https://github.com/golang/go/blob/master/src/net/rpc/client.go#L41 "View Source")
```
type Client struct {
// 內含隱藏或非導出字段
}
```
Client類型代表RPC客戶端。同一個客戶端可能有多個未返回的調用,也可能被多個go程同時使用。
### func [NewClient](https://github.com/golang/go/blob/master/src/net/rpc/client.go#L188 "View Source")
```
func NewClient(conn io.ReadWriteCloser) *Client
```
NewClient返回一個新的Client,以管理對連接另一端的服務的請求。它添加緩沖到連接的寫入側,以便將回復的頭域和有效負載作為一個單元發送。
### func [NewClientWithCodec](https://github.com/golang/go/blob/master/src/net/rpc/client.go#L196 "View Source")
```
func NewClientWithCodec(codec ClientCodec) *Client
```
NewClientWithCodec類似NewClient,但使用指定的編解碼器,以編碼請求主體和解碼回復主體。
### func [Dial](https://github.com/golang/go/blob/master/src/net/rpc/client.go#L269 "View Source")
```
func Dial(network, address string) (*Client, error)
```
Dial在指定的網絡和地址與RPC服務端連接。
### func [DialHTTP](https://github.com/golang/go/blob/master/src/net/rpc/client.go#L236 "View Source")
```
func DialHTTP(network, address string) (*Client, error)
```
DialHTTP在指定的網絡和地址與在默認HTTP RPC路徑監聽的HTTP RPC服務端連接。
### func [DialHTTPPath](https://github.com/golang/go/blob/master/src/net/rpc/client.go#L242 "View Source")
```
func DialHTTPPath(network, address, path string) (*Client, error)
```
DialHTTPPath在指定的網絡、地址和路徑與HTTP RPC服務端連接。
### func (\*Client) [Call](https://github.com/golang/go/blob/master/src/net/rpc/client.go#L314 "View Source")
```
func (client *Client) Call(serviceMethod string, args interface{}, reply interface{}) error
```
Call調用指定的方法,等待調用返回,將結果寫入reply,然后返回執行的錯誤狀態。
### func (\*Client) [Go](https://github.com/golang/go/blob/master/src/net/rpc/client.go#L292 "View Source")
```
func (client *Client) Go(serviceMethod string, args interface{}, reply interface{}, done chan *Call) *Call
```
Go異步的調用函數。本方法Call結構體類型指針的返回值代表該次遠程調用。通道類型的參數done會在本次調用完成時發出信號(通過返回本次Go方法的返回值)。如果done為nil,Go會申請一個新的通道(寫入返回值的Done字段);如果done非nil,done必須有緩沖,否則Go方法會故意崩潰。
### func (\*Client) [Close](https://github.com/golang/go/blob/master/src/net/rpc/client.go#L277 "View Source")
```
func (client *Client) Close() error
```
## type [Server](https://github.com/golang/go/blob/master/src/net/rpc/server.go#L184 "View Source")
```
type Server struct {
// 內含隱藏或非導出字段
}
```
Server代表RPC服務端。
### func [NewServer](https://github.com/golang/go/blob/master/src/net/rpc/server.go#L194 "View Source")
```
func NewServer() *Server
```
NewServer創建并返回一個\*Server。
### func (\*Server) [Register](https://github.com/golang/go/blob/master/src/net/rpc/server.go#L227 "View Source")
```
func (server *Server) Register(rcvr interface{}) error
```
Register在server注冊并公布rcvr的方法集中滿足如下要求的方法:
```
- 方法是導出的
- 方法有兩個參數,都是導出類型或內建類型
- 方法的第二個參數是指針
- 方法只有一個error接口類型的返回值
```
如果rcvr不是一個導出類型的值,或者該類型沒有滿足要求的方法,Register會返回錯誤。Register也會使用[log](http://godoc.org/log)包將錯誤寫入日志。客戶端可以使用格式為"Type.Method"的字符串訪問這些方法,其中Type是rcvr的具體類型。
### func (\*Server) [RegisterName](https://github.com/golang/go/blob/master/src/net/rpc/server.go#L233 "View Source")
```
func (server *Server) RegisterName(name string, rcvr interface{}) error
```
RegisterName類似Register,但使用提供的name代替rcvr的具體類型名作為服務名。
### func (\*Server) [Accept](https://github.com/golang/go/blob/master/src/net/rpc/server.go#L592 "View Source")
```
func (server *Server) Accept(lis net.Listener)
```
Accept接收監聽器l獲取的連接,然后服務每一個連接。Accept會阻塞,調用者應另開線程:"go server.Accept(l)"
### func (\*Server) [ServeConn](https://github.com/golang/go/blob/master/src/net/rpc/server.go#L427 "View Source")
```
func (server *Server) ServeConn(conn io.ReadWriteCloser)
```
ServeConn在單個連接上執行server。ServeConn會阻塞,服務該連接直到客戶端掛起。調用者一般應另開線程調用本函數:"go server.ServeConn(conn)"。ServeConn在該連接使用gob(參見encoding/gob包)有線格式。要使用其他的編解碼器,可調用ServeCodec方法。
### func (\*Server) [ServeCodec](https://github.com/golang/go/blob/master/src/net/rpc/server.go#L435 "View Source")
```
func (server *Server) ServeCodec(codec ServerCodec)
```
ServeCodec類似ServeConn,但使用指定的編解碼器,以編碼請求主體和解碼回復主體。
### func (\*Server) [ServeRequest](https://github.com/golang/go/blob/master/src/net/rpc/server.go#L460 "View Source")
```
func (server *Server) ServeRequest(codec ServerCodec) error
```
ServeRequest類似ServeCodec,但異步的服務單個請求。它不會在調用結束后關閉codec。
### func (\*Server) [ServeHTTP](https://github.com/golang/go/blob/master/src/net/rpc/server.go#L657 "View Source")
```
func (server *Server) ServeHTTP(w http.ResponseWriter, req *http.Request)
```
ServeHTTP實現了回應RPC請求的http.Handler接口。
### func (\*Server) [HandleHTTP](https://github.com/golang/go/blob/master/src/net/rpc/server.go#L676 "View Source")
```
func (server *Server) HandleHTTP(rpcPath, debugPath string)
```
HandleHTTP注冊server的RPC信息HTTP處理器對應到rpcPath,注冊server的debug信息HTTP處理器對應到debugPath。HandleHTTP會注冊到http.DefaultServeMux。之后,仍需要調用http.Serve(),一般會另開線程:"go http.Serve(l, nil)"
## func [Register](https://github.com/golang/go/blob/master/src/net/rpc/server.go#L603 "View Source")
```
func Register(rcvr interface{}) error
```
Register在DefaultServer注冊并公布rcvr的方法。
## func [RegisterName](https://github.com/golang/go/blob/master/src/net/rpc/server.go#L607 "View Source")
```
func RegisterName(name string, rcvr interface{}) error
```
RegisterName函數類似Register函數,但使用提供的name代替rcvr的具體類型名作為服務名。
## func [Accept](https://github.com/golang/go/blob/master/src/net/rpc/server.go#L651 "View Source")
```
func Accept(lis net.Listener)
```
Accept接收監聽器l獲取的連接,然后將每一個連接交給DefaultServer服務。Accept會阻塞,調用者應另開線程:"go server.Accept(l)"
## func [ServeConn](https://github.com/golang/go/blob/master/src/net/rpc/server.go#L632 "View Source")
```
func ServeConn(conn io.ReadWriteCloser)
```
ServeConn在單個連接上執行DefaultServer。ServeConn會阻塞,服務該連接直到客戶端掛起。調用者一般應另開線程調用本函數:"go ServeConn(conn)"。ServeConn在該連接使用gob(參見encoding/gob包)有線格式。要使用其他的編解碼器,可調用ServeCodec方法。
## func [ServeCodec](https://github.com/golang/go/blob/master/src/net/rpc/server.go#L638 "View Source")
```
func ServeCodec(codec ServerCodec)
```
ServeCodec類似ServeConn,但使用指定的編解碼器,以編碼請求主體和解碼回復主體。
## func [ServeRequest](https://github.com/golang/go/blob/master/src/net/rpc/server.go#L644 "View Source")
```
func ServeRequest(codec ServerCodec) error
```
ServeRequest類似ServeCodec,但異步的服務單個請求。它不會在調用結束后關閉codec。
## func [HandleHTTP](https://github.com/golang/go/blob/master/src/net/rpc/server.go#L684 "View Source")
```
func HandleHTTP()
```
HandleHTTP函數注冊DefaultServer的RPC信息HTTP處理器對應到DefaultRPCPath,和DefaultServer的debug處理器對應到DefaultDebugPath。HandleHTTP函數會注冊到http.DefaultServeMux。之后,仍需要調用http.Serve(),一般會另開線程:"go http.Serve(l, nil)"
- 庫
- package achive
- package tar
- package zip
- package bufio
- package builtin
- package bytes
- package compress
- package bzip2
- package flate
- package gzip
- package lzw
- package zlib
- package container
- package heap
- package list
- package ring
- package crypto
- package aes
- package cipher
- package des
- package dsa
- package ecdsa
- package elliptic
- package hmac
- package md5
- package rand
- package rc4
- package rsa
- package sha1
- package sha256
- package sha512
- package subtle
- package tls
- package x509
- package pkix
- package database
- package sql
- package driver
- package encoding
- package ascii85
- package asn1
- package base32
- package base64
- package binary
- package csv
- package gob
- package hex
- package json
- package pem
- package xml
- package errors
- package expvar
- package flag
- package fmt
- package go
- package doc
- package format
- package parser
- package printer
- package hash
- package adler32
- package crc32
- package crc64
- package fnv
- package html
- package template
- package image
- package color
- package palette
- package draw
- package gif
- package jpeg
- package png
- package index
- package suffixarray
- package io
- package ioutil
- package log
- package syslog
- package math
- package big
- package cmplx
- package rand
- package mime
- package multipart
- package net
- package http
- package cgi
- package cookiejar
- package fcgi
- package httptest
- package httputil
- package pprof
- package mail
- package rpc
- package jsonrpc
- package smtp
- package textproto
- package url
- package os
- package exec
- package signal
- package user
- package path
- package filepath
- package reflect
- package regexp
- package runtime
- package cgo
- package debug
- package pprof
- package race
- package sort
- package strconv
- package strings
- package sync
- package atomic
- package text
- package scanner
- package tabwriter
- package template
- package time
- package unicode
- package utf16
- package utf8
- package unsafe