func (c *Client) sendPostHandler() {
out:
	for {
		select {
		case details := <-c.sendPostChan:
			c.handleSendPostMessage(details)
		case <-c.shutdown:
			break out
		}
	}
cleanup:
	for {
		select {
		case details := <-c.sendPostChan:
			details.jsonRequest.responseChan <- &response{
				result: nil,
				err:    ErrClientShutdown,
			}
		default:
			break cleanup
		}
	}
	c.wg.Done()
	log.Tracef("RPC client send handler done for %s", c.config.Host)
}
sendPostHandler handles all outgoing messages when the client is running
in HTTP POST mode.  It uses a buffered channel to serialize output messages
while allowing the sender to continue running asynchronously.  It must be run
as a goroutine.
package rpcclient
import (
	"bytes"
	"container/list"
	"crypto/tls"
	"crypto/x509"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"sync"
	"sync/atomic"
	"github.com/stevenroose/go-bitcoin-core-rpc/btcjson"
)
var (
	ErrClientShutdown = errors.New("the client has been shutdown")
)
const (
	sendPostBufferSize = 100
)
type sendPostDetails struct {
	httpRequest *http.Request
	jsonRequest *jsonRequest
}
type jsonRequest struct {
	id             uint64
	method         string
	cmd            interface{}
	marshalledJSON []byte
	responseChan   chan *response
}
type Client struct {
	id uint64  
	config *ConnConfig
	httpClient *http.Client
	requestLock sync.Mutex
	requestList *list.List
	sendPostChan chan *sendPostDetails
	shutdown     chan struct{}
	wg           sync.WaitGroup
}
func (c *Client) NextID() uint64 {
	return atomic.AddUint64(&c.id, 1)
}
type rawResponse struct {
	ID     *float64          `json:"id"`
	Result json.RawMessage   `json:"result"`
	Error  *btcjson.RPCError `json:"error"`
}
type response struct {
	result []byte
	err    error
}
func (r rawResponse) result() (result []byte, err error) {
	if r.Error != nil {
		return nil, r.Error
	}
	return r.Result, nil
}
func (c *Client) handleSendPostMessage(details *sendPostDetails) {
	jReq := details.jsonRequest
	log.Tracef("Sending command [%s] with id %d", jReq.method, jReq.id)
	httpResponse, err := c.httpClient.Do(details.httpRequest)
	if err != nil {
		jReq.responseChan <- &response{err: err}
		return
	}
	respBytes, err := ioutil.ReadAll(httpResponse.Body)
	_ = httpResponse.Body.Close()
	if err != nil {
		err = fmt.Errorf("error reading json reply: %v", err)
		jReq.responseChan <- &response{err: err}
		return
	}
	var resp rawResponse
	err = json.Unmarshal(respBytes, &resp)
	if err != nil {
		err = fmt.Errorf("status code: %d, response: %q",
			httpResponse.StatusCode, string(respBytes))
		jReq.responseChan <- &response{err: err}
		return
	}
	res, err := resp.result()
	jReq.responseChan <- &response{result: res, err: err}
}