func NewClientTLSFromFile(certFile, serverName string) (TransportAuthenticator, error) {
	b, err := ioutil.ReadFile(certFile)
	if err != nil {
		return nil, err
	}
	cp := x509.NewCertPool()
	if !cp.AppendCertsFromPEM(b) {
		return nil, fmt.Errorf("credentials: failed to append certificates")
	}
	return NewTLS(&tls.Config{ServerName: serverName, RootCAs: cp}), nil
}
NewClientTLSFromFile constructs a TLS from the input certificate file for client.
package credentials
import (
	"crypto/tls"
	"crypto/x509"
	"fmt"
	"io/ioutil"
	"net"
	"strings"
	"time"
	"golang.org/x/net/context"
)
var (
	alpnProtoStr = []string{"h2"}
)
type Credentials interface {
	GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error)
	RequireTransportSecurity() bool
}
type ProtocolInfo struct {
	ProtocolVersion string
	SecurityProtocol string
	SecurityVersion string
}
type AuthInfo interface {
	AuthType() string
}
type TransportAuthenticator interface {
	ClientHandshake(addr string, rawConn net.Conn, timeout time.Duration) (net.Conn, AuthInfo, error)
	ServerHandshake(rawConn net.Conn) (net.Conn, AuthInfo, error)
	Info() ProtocolInfo
	Credentials
}
type TLSInfo struct {
	State tls.ConnectionState
}
func (t TLSInfo) AuthType() string {
	return "tls"
}
type tlsCreds struct {
	config tls.Config
}
func (c tlsCreds) Info() ProtocolInfo {
	return ProtocolInfo{
		SecurityProtocol: "tls",
		SecurityVersion:  "1.2",
	}
}
func (c *tlsCreds) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
	return nil, nil
}
func (c *tlsCreds) RequireTransportSecurity() bool {
	return true
}
type timeoutError struct{}
func (timeoutError) Error() string   { return "credentials: Dial timed out" }
func (timeoutError) Timeout() bool   { return true }
func (timeoutError) Temporary() bool { return true }
func (c *tlsCreds) ClientHandshake(addr string, rawConn net.Conn, timeout time.Duration) (_ net.Conn, _ AuthInfo, err error) {
	var errChannel chan error
	if timeout != 0 {
		errChannel = make(chan error, 2)
		time.AfterFunc(timeout, func() {
			errChannel <- timeoutError{}
		})
	}
	if c.config.ServerName == "" {
		colonPos := strings.LastIndex(addr, ":")
		if colonPos == -1 {
			colonPos = len(addr)
		}
		c.config.ServerName = addr[:colonPos]
	}
	conn := tls.Client(rawConn, &c.config)
	if timeout == 0 {
		err = conn.Handshake()
	} else {
		go func() {
			errChannel <- conn.Handshake()
		}()
		err = <-errChannel
	}
	if err != nil {
		rawConn.Close()
		return nil, nil, err
	}
	return conn, nil, nil
}
func (c *tlsCreds) ServerHandshake(rawConn net.Conn) (net.Conn, AuthInfo, error) {
	conn := tls.Server(rawConn, &c.config)
	if err := conn.Handshake(); err != nil {
		rawConn.Close()
		return nil, nil, err
	}
	return conn, TLSInfo{conn.ConnectionState()}, nil
}
func NewTLS(c *tls.Config) TransportAuthenticator {
	tc := &tlsCreds{*c}
	tc.config.NextProtos = alpnProtoStr
	return tc
}
func NewClientTLSFromCert(cp *x509.CertPool, serverName string) TransportAuthenticator {
	return NewTLS(&tls.Config{ServerName: serverName, RootCAs: cp})
}