golang go1.4 TestMain示例

go1.4 TestMain示例

testmain_example_test.go
package example_test

import (
	"os"
	"testing"
)

func TestA(t *testing.T) {
}

func TestB(t *testing.T) {
}

func setup() {
	println("setup")
}

func teardown() {
	println("teardown")
}

func TestMain(m *testing.M) {
	setup()
	ret := m.Run()
	if ret == 0 {
		teardown()
	}
	os.Exit(ret)
}

golang Go和MongoDB的JSON-API:最终部分

Go和MongoDB的JSON-API:最终部分

main.go
package main

import (
	"encoding/json"
	"log"
	"net/http"
	"reflect"
	"time"

	"github.com/gorilla/context"
	"github.com/julienschmidt/httprouter"
	"github.com/justinas/alice"
	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
)

// Repo

type Tea struct {
	Id       bson.ObjectId `json:"id,omitempty" bson:"_id,omitempty"`
	Name     string        `json:"name"`
	Category string        `json:"category"`
}

type TeasCollection struct {
	Data []Tea `json:"data"`
}

type TeaResource struct {
	Data Tea `json:"data"`
}

type TeaRepo struct {
	coll *mgo.Collection
}

func (r *TeaRepo) All() (TeasCollection, error) {
	result := TeasCollection{[]Tea{}}
	err := r.coll.Find(nil).All(&result.Data)
	if err != nil {
		return result, err
	}

	return result, nil
}

func (r *TeaRepo) Find(id string) (TeaResource, error) {
	result := TeaResource{}
	err := r.coll.FindId(bson.ObjectIdHex(id)).One(&result.Data)
	if err != nil {
		return result, err
	}

	return result, nil
}

func (r *TeaRepo) Create(tea *Tea) error {
	id := bson.NewObjectId()
	_, err := r.coll.UpsertId(id, tea)
	if err != nil {
		return err
	}

	tea.Id = id

	return nil
}

func (r *TeaRepo) Update(tea *Tea) error {
	err := r.coll.UpdateId(tea.Id, tea)
	if err != nil {
		return err
	}

	return nil
}

func (r *TeaRepo) Delete(id string) error {
	err := r.coll.RemoveId(bson.ObjectIdHex(id))
	if err != nil {
		return err
	}

	return nil
}

// Errors

type Errors struct {
	Errors []*Error `json:"errors"`
}

type Error struct {
	Id     string `json:"id"`
	Status int    `json:"status"`
	Title  string `json:"title"`
	Detail string `json:"detail"`
}

func WriteError(w http.ResponseWriter, err *Error) {
	w.Header().Set("Content-Type", "application/vnd.api+json")
	w.WriteHeader(err.Status)
	json.NewEncoder(w).Encode(Errors{[]*Error{err}})
}

var (
	ErrBadRequest           = &Error{"bad_request", 400, "Bad request", "Request body is not well-formed. It must be JSON."}
	ErrNotAcceptable        = &Error{"not_acceptable", 406, "Not Acceptable", "Accept header must be set to 'application/vnd.api+json'."}
	ErrUnsupportedMediaType = &Error{"unsupported_media_type", 415, "Unsupported Media Type", "Content-Type header must be set to: 'application/vnd.api+json'."}
	ErrInternalServer       = &Error{"internal_server_error", 500, "Internal Server Error", "Something went wrong."}
)

// Middlewares

func recoverHandler(next http.Handler) http.Handler {
	fn := func(w http.ResponseWriter, r *http.Request) {
		defer func() {
			if err := recover(); err != nil {
				log.Printf("panic: %+v", err)
				WriteError(w, ErrInternalServer)
			}
		}()

		next.ServeHTTP(w, r)
	}

	return http.HandlerFunc(fn)
}

func loggingHandler(next http.Handler) http.Handler {
	fn := func(w http.ResponseWriter, r *http.Request) {
		t1 := time.Now()
		next.ServeHTTP(w, r)
		t2 := time.Now()
		log.Printf("[%s] %q %v\n", r.Method, r.URL.String(), t2.Sub(t1))
	}

	return http.HandlerFunc(fn)
}

func acceptHandler(next http.Handler) http.Handler {
	fn := func(w http.ResponseWriter, r *http.Request) {
		if r.Header.Get("Accept") != "application/vnd.api+json" {
			WriteError(w, ErrNotAcceptable)
			return
		}

		next.ServeHTTP(w, r)
	}

	return http.HandlerFunc(fn)
}

func contentTypeHandler(next http.Handler) http.Handler {
	fn := func(w http.ResponseWriter, r *http.Request) {
		if r.Header.Get("Content-Type") != "application/vnd.api+json" {
			WriteError(w, ErrUnsupportedMediaType)
			return
		}

		next.ServeHTTP(w, r)
	}

	return http.HandlerFunc(fn)
}

func bodyHandler(v interface{}) func(http.Handler) http.Handler {
	t := reflect.TypeOf(v)

	m := func(next http.Handler) http.Handler {
		fn := func(w http.ResponseWriter, r *http.Request) {
			val := reflect.New(t).Interface()
			err := json.NewDecoder(r.Body).Decode(val)

			if err != nil {
				WriteError(w, ErrBadRequest)
				return
			}

			if next != nil {
				context.Set(r, "body", val)
				next.ServeHTTP(w, r)
			}
		}

		return http.HandlerFunc(fn)
	}

	return m
}

// Main handlers

type appContext struct {
	db *mgo.Database
}

func (c *appContext) teasHandler(w http.ResponseWriter, r *http.Request) {
	repo := TeaRepo{c.db.C("teas")}
	teas, err := repo.All()
	if err != nil {
		panic(err)
	}

	w.Header().Set("Content-Type", "application/vnd.api+json")
	json.NewEncoder(w).Encode(teas)
}

func (c *appContext) teaHandler(w http.ResponseWriter, r *http.Request) {
	params := context.Get(r, "params").(httprouter.Params)
	repo := TeaRepo{c.db.C("teas")}
	tea, err := repo.Find(params.ByName("id"))
	if err != nil {
		panic(err)
	}

	w.Header().Set("Content-Type", "application/vnd.api+json")
	json.NewEncoder(w).Encode(tea)
}

func (c *appContext) createTeaHandler(w http.ResponseWriter, r *http.Request) {
	body := context.Get(r, "body").(*TeaResource)
	repo := TeaRepo{c.db.C("teas")}
	err := repo.Create(&body.Data)
	if err != nil {
		panic(err)
	}

	w.Header().Set("Content-Type", "application/vnd.api+json")
	w.WriteHeader(201)
	json.NewEncoder(w).Encode(body)
}

func (c *appContext) updateTeaHandler(w http.ResponseWriter, r *http.Request) {
	params := context.Get(r, "params").(httprouter.Params)
	body := context.Get(r, "body").(*TeaResource)
	body.Data.Id = bson.ObjectIdHex(params.ByName("id"))
	repo := TeaRepo{c.db.C("teas")}
	err := repo.Update(&body.Data)
	if err != nil {
		panic(err)
	}

	w.WriteHeader(204)
	w.Write([]byte("\n"))
}

func (c *appContext) deleteTeaHandler(w http.ResponseWriter, r *http.Request) {
	params := context.Get(r, "params").(httprouter.Params)
	repo := TeaRepo{c.db.C("teas")}
	err := repo.Delete(params.ByName("id"))
	if err != nil {
		panic(err)
	}

	w.WriteHeader(204)
	w.Write([]byte("\n"))
}

// Router

type router struct {
	*httprouter.Router
}

func (r *router) Get(path string, handler http.Handler) {
	r.GET(path, wrapHandler(handler))
}

func (r *router) Post(path string, handler http.Handler) {
	r.POST(path, wrapHandler(handler))
}

func (r *router) Put(path string, handler http.Handler) {
	r.PUT(path, wrapHandler(handler))
}

func (r *router) Delete(path string, handler http.Handler) {
	r.DELETE(path, wrapHandler(handler))
}

func NewRouter() *router {
	return &router{httprouter.New()}
}

func wrapHandler(h http.Handler) httprouter.Handle {
	return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
		context.Set(r, "params", ps)
		h.ServeHTTP(w, r)
	}
}

func main() {
	session, err := mgo.Dial("localhost")
	if err != nil {
		panic(err)
	}
	defer session.Close()
	session.SetMode(mgo.Monotonic, true)

	appC := appContext{session.DB("test")}
	commonHandlers := alice.New(context.ClearHandler, loggingHandler, recoverHandler, acceptHandler)
	router := NewRouter()
	router.Get("/teas/:id", commonHandlers.ThenFunc(appC.teaHandler))
	router.Put("/teas/:id", commonHandlers.Append(contentTypeHandler, bodyHandler(TeaResource{})).ThenFunc(appC.updateTeaHandler))
	router.Delete("/teas/:id", commonHandlers.ThenFunc(appC.deleteTeaHandler))
	router.Get("/teas", commonHandlers.ThenFunc(appC.teasHandler))
	router.Post("/teas", commonHandlers.Append(contentTypeHandler, bodyHandler(TeaResource{})).ThenFunc(appC.createTeaHandler))
	http.ListenAndServe(":8080", router)
}

golang 转到SSH服务器完整示例 - 在此处阅读更多内容https://blog.gopheracademy.com/go-and-ssh/

转到SSH服务器完整示例 - 在此处阅读更多内容https://blog.gopheracademy.com/go-and-ssh/

sshd.go
// A small SSH daemon providing bash sessions
//
// Server:
// cd my/new/dir/
// #generate server keypair
// ssh-keygen -t rsa
// go get -v .
// go run sshd.go
//
// Client:
// ssh foo@localhost -p 2200 #pass=bar

package main

import (
	"encoding/binary"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net"
	"os/exec"
	"sync"
	"syscall"
	"unsafe"

	"github.com/kr/pty"
	"golang.org/x/crypto/ssh"
)

func main() {

	// In the latest version of crypto/ssh (after Go 1.3), the SSH server type has been removed
	// in favour of an SSH connection type. A ssh.ServerConn is created by passing an existing
	// net.Conn and a ssh.ServerConfig to ssh.NewServerConn, in effect, upgrading the net.Conn
	// into an ssh.ServerConn

	config := &ssh.ServerConfig{
		//Define a function to run when a client attempts a password login
		PasswordCallback: func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) {
			// Should use constant-time compare (or better, salt+hash) in a production setting.
			if c.User() == "foo" && string(pass) == "bar" {
				return nil, nil
			}
			return nil, fmt.Errorf("password rejected for %q", c.User())
		},
		// You may also explicitly allow anonymous client authentication, though anon bash
		// sessions may not be a wise idea
		// NoClientAuth: true,
	}

	// You can generate a keypair with 'ssh-keygen -t rsa'
	privateBytes, err := ioutil.ReadFile("id_rsa")
	if err != nil {
		log.Fatal("Failed to load private key (./id_rsa)")
	}

	private, err := ssh.ParsePrivateKey(privateBytes)
	if err != nil {
		log.Fatal("Failed to parse private key")
	}

	config.AddHostKey(private)

	// Once a ServerConfig has been configured, connections can be accepted.
	listener, err := net.Listen("tcp", "0.0.0.0:2200")
	if err != nil {
		log.Fatalf("Failed to listen on 2200 (%s)", err)
	}

	// Accept all connections
	log.Print("Listening on 2200...")
	for {
		tcpConn, err := listener.Accept()
		if err != nil {
			log.Printf("Failed to accept incoming connection (%s)", err)
			continue
		}
		// Before use, a handshake must be performed on the incoming net.Conn.
		sshConn, chans, reqs, err := ssh.NewServerConn(tcpConn, config)
		if err != nil {
			log.Printf("Failed to handshake (%s)", err)
			continue
		}

		log.Printf("New SSH connection from %s (%s)", sshConn.RemoteAddr(), sshConn.ClientVersion())
		// Discard all global out-of-band Requests
		go ssh.DiscardRequests(reqs)
		// Accept all channels
		go handleChannels(chans)
	}
}

func handleChannels(chans <-chan ssh.NewChannel) {
	// Service the incoming Channel channel in go routine
	for newChannel := range chans {
		go handleChannel(newChannel)
	}
}

func handleChannel(newChannel ssh.NewChannel) {
	// Since we're handling a shell, we expect a
	// channel type of "session". The also describes
	// "x11", "direct-tcpip" and "forwarded-tcpip"
	// channel types.
	if t := newChannel.ChannelType(); t != "session" {
		newChannel.Reject(ssh.UnknownChannelType, fmt.Sprintf("unknown channel type: %s", t))
		return
	}

	// At this point, we have the opportunity to reject the client's
	// request for another logical connection
	connection, requests, err := newChannel.Accept()
	if err != nil {
		log.Printf("Could not accept channel (%s)", err)
		return
	}

	// Fire up bash for this session
	bash := exec.Command("bash")

	// Prepare teardown function
	close := func() {
		connection.Close()
		_, err := bash.Process.Wait()
		if err != nil {
			log.Printf("Failed to exit bash (%s)", err)
		}
		log.Printf("Session closed")
	}

	// Allocate a terminal for this channel
	log.Print("Creating pty...")
	bashf, err := pty.Start(bash)
	if err != nil {
		log.Printf("Could not start pty (%s)", err)
		close()
		return
	}

	//pipe session to bash and visa-versa
	var once sync.Once
	go func() {
		io.Copy(connection, bashf)
		once.Do(close)
	}()
	go func() {
		io.Copy(bashf, connection)
		once.Do(close)
	}()

	// Sessions have out-of-band requests such as "shell", "pty-req" and "env"
	go func() {
		for req := range requests {
			switch req.Type {
			case "shell":
				// We only accept the default shell
				// (i.e. no command in the Payload)
				if len(req.Payload) == 0 {
					req.Reply(true, nil)
				}
			case "pty-req":
				termLen := req.Payload[3]
				w, h := parseDims(req.Payload[termLen+4:])
				SetWinsize(bashf.Fd(), w, h)
				// Responding true (OK) here will let the client
				// know we have a pty ready for input
				req.Reply(true, nil)
			case "window-change":
				w, h := parseDims(req.Payload)
				SetWinsize(bashf.Fd(), w, h)
			}
		}
	}()
}

// =======================

// parseDims extracts terminal dimensions (width x height) from the provided buffer.
func parseDims(b []byte) (uint32, uint32) {
	w := binary.BigEndian.Uint32(b)
	h := binary.BigEndian.Uint32(b[4:])
	return w, h
}

// ======================

// Winsize stores the Height and Width of a terminal.
type Winsize struct {
	Height uint16
	Width  uint16
	x      uint16 // unused
	y      uint16 // unused
}

// SetWinsize sets the size of the given pty.
func SetWinsize(fd uintptr, w, h uint32) {
	ws := &Winsize{Width: uint16(w), Height: uint16(h)}
	syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(syscall.TIOCSWINSZ), uintptr(unsafe.Pointer(ws)))
}

// Borrowed from https://github.com/creack/termios/blob/master/win/win.go

golang 使用接口进行从字符串到Struct的类型转换的基本示例

使用接口进行从字符串到Struct的类型转换的基本示例

nativecmdr.go
// nativecmdr project nativecmdr.go
package main

import (
	"bytes"
	"fmt"
	"log"
	"os/exec"
	"strconv"
	"strings"
	"syscall"
)

const (
	ENOSLC        = "failed to produce slice of values"
	ENOMATRIX     = "there are no x,y elements in matrix"
	PYCMD         = "/usr/local/bin/python"
	PYARG_WORK    = "for i in range(0, 16): print('%d,%d' % (i, i*i))"
	PYARG_NO_WORK = "for i in range(0, 16): print('%d:%d' % (i, i*i))"
)

type Nativer interface {
	NativeType(s string) error
	HasError() bool
}

type MatrixArrayResult struct {
	Xprime   []int
	Yprime   []int
	Error    error
	ExitCode int
}

type CmdResult struct {
	Stdout   string
	Stderr   string
	ExitCode int
}

func (m *MatrixArrayResult) HasError() bool {
	if m.ExitCode == 0 {
		return false
	} else {
		return true
	}
}

func (m *MatrixArrayResult) NativeType(s string) error {

	var mkerr = func(s string) error {
		return fmt.Errorf("%v", s)
	}

	var strslc = strings.Split(s, "\n")
	if len(strslc) < 1 {
		m.Error = mkerr(ENOSLC)
		return mkerr(ENOSLC)
	}
	for _, val := range strslc {
		tm := strings.Split(val, ",")
		if len(tm) < 2 { // range errors are not what we want
			break
		}
		x, _ := strconv.Atoi(tm[0]) // Unchecked err
		y, _ := strconv.Atoi(tm[1]) // Unchecked err
		m.Xprime = append(m.Xprime, x)
		m.Yprime = append(m.Yprime, y)
	}

	if len(m.Xprime) < 1 || len(m.Yprime) < 1 {
		m.Error = mkerr(ENOMATRIX)
		return mkerr(ENOMATRIX)
	}

	return nil
}

func ErrHandle(e error) error {
	if e != nil {
		log.Printf("%v", fmt.Errorf("%v", e.Error()))
		return e
	}
	return nil
}

func RunCmd(ex Nativer, command string, args ...string) error {
	var result CmdResult

	cmd := exec.Command(command, args...)

	// Stdout buffer
	cmdOutput := &bytes.Buffer{}

	// Attach buffer to command
	cmd.Stdout = cmdOutput

	//Stderr buffer
	cmdError := &bytes.Buffer{}

	//Attach buffer to cmd
	cmd.Stderr = cmdError

	var waitStatus syscall.WaitStatus

	if err := cmd.Run(); err != nil {
		//Grab stderr
		result.Stderr = string(cmdError.Bytes())

		// Did the command fail because of an unsuccessful exit code
		if exitError, ok := err.(*exec.ExitError); ok {

			waitStatus = exitError.Sys().(syscall.WaitStatus)

			//Store exit code
			result.ExitCode = waitStatus.ExitStatus()
		} else {
			//There was not exit error because the command never ran.
			//Let's set an error ourselves so there is no confusion.
			result.Stderr = fmt.Sprintf("error running command: %s", command)

			//Store exit code for Bash command not found
			result.ExitCode = 127
		}
	} else {
		//Grab stdout and stuff it into return stdout as string
		result.Stdout = string(cmdOutput.Bytes())

		// Command was successful
		waitStatus = cmd.ProcessState.Sys().(syscall.WaitStatus)

		//Store exit code
		result.ExitCode = waitStatus.ExitStatus()
	}

	if e := ex.NativeType(result.Stdout); e != nil {
		return nil // In reality this should return `e` instead of nil
	}

	return nil
}

func main() {
	var Amatrix Nativer = &MatrixArrayResult{}
	var Bmatrix Nativer = &MatrixArrayResult{}
	//var Amatrix = Nativer(&MatrixArrayResult{}) // A bit more ugly than above
	//var Bmatrix = Nativer(&MatrixArrayResult{})

	// This should work, Nil error
	if e := RunCmd(Amatrix, PYCMD, "-c", PYARG_WORK); e == nil {
		fmt.Printf("Matrix Xs: %v\nMatrix Ys: %v\nError: %v\n",
			Amatrix.(*MatrixArrayResult).Xprime, // assertions must be checked
			Amatrix.(*MatrixArrayResult).Yprime,
			Amatrix.(*MatrixArrayResult).Error)
	}

	// This should not work, non-Nil error
	if e := RunCmd(Bmatrix, PYCMD, "-c", PYARG_NO_WORK); e == nil {
		fmt.Printf("Matrix Xs: %v\nMatrix Ys: %v\nError: %v\n",
			Bmatrix.(*MatrixArrayResult).Xprime, // assertions must be checked
			Bmatrix.(*MatrixArrayResult).Yprime,
			Bmatrix.(*MatrixArrayResult).Error)
	}
	//
	// Results of running above should look something like this:
	//
	//Matrix Xs: [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15]
	//Matrix Ys: [0 1 4 9 16 25 36 49 64 81 100 121 144 169 196 225]
	//Error: <nil>
	//Matrix Xs: []
	//Matrix Ys: []
	//Error: there are no x,y elements in matrix

}
mknativetype.go
// mknativetype project main.go
package main

import (
	"fmt"
	"strconv"
	"strings"
)

type Nativer interface {
	NativeType(s string) error
}

type Foo struct {
	Fruit string
	Veg   string
	Array []byte
}

type Bar struct {
	First string
	Last  string
	Array []byte
}

type Matrix struct {
	X int
	Y int
}

func (m *Matrix) NativeType(s string) error {
	var sep = ","
	var strslc = strings.SplitN(s, sep, 4)
	m.X, _ = strconv.Atoi(strslc[0])
	m.Y, _ = strconv.Atoi(strslc[2])
	return nil
}

func (f *Foo) NativeType(s string) error {
	var sep = ";"
	var strslc = strings.SplitN(s, sep, 3)
	f.Fruit = strslc[0]
	f.Veg = strslc[1]
	f.Array = []byte(s)
	return nil
}

func (b *Bar) NativeType(s string) error {
	var sep = " "
	var strslc = strings.SplitN(s, sep, 5)
	b.First = strslc[2]
	b.Last = strslc[3]
	b.Array = []byte(fmt.Sprintf("%s %s", strslc[2], strslc[3]))
	return nil
}

func MimicCommand(s string, n Nativer) error {
	err := n.NativeType(s)
	if err != nil {
		return fmt.Errorf("%s", "poof")
	}
	return nil
}

func main() {
	var f1 Nativer = &Foo{}
	var b1 Nativer = &Bar{}
	var m1 Nativer = &Matrix{}

	MimicCommand("apple;detroit-red beet;banana;sweet potato", f1)
	MimicCommand("junk more.junk Joe Buckeye is a Ducks Fan", b1)
	MimicCommand("100,-0.5,20,-0.3", m1)

	fmt.Printf("Food -- Fruit: %v Vegetable: %v Array: %v\n", f1.(*Foo).Fruit, f1.(*Foo).Veg, f1.(*Foo).Array)
	fmt.Printf("Name -- First: %v Last: %v Array: %v\n", b1.(*Bar).First, b1.(*Bar).Last, b1.(*Bar).Array)
	fmt.Printf("Matrix -- X: %v Y: %v\n", m1.(*Matrix).X, m1.(*Matrix).Y)

}

golang 从切片中删除元素

从切片中删除元素

remove.go
func remove(array []interface{}, index int) []interface{} {
	if index < 0 || index > len(array) {
		return array
	}
	return append(array[0:index], array[index+1:]...)
}

golang 在切片中查找元素

在切片中查找元素

find.go
func find(array []interface{}, item interface{}) (index int) {
	index = -1
	for idx, value := range array {
		if value == item {
			index = idx
			break
		}
	}
	return
}

golang 去lang SSH连接

去lang SSH连接

ssh.go
package main

import (
  "bytes"
  "code.google.com/p/go.crypto/ssh"
  "fmt"
  "io/ioutil"
  "os"
)

func main() {
  pk, _ := ioutil.ReadFile(os.Getenv("HOME") + "/.ssh/id_rsa")
  signer, err := ssh.ParsePrivateKey(pk)

  if err != nil {
    panic(err)
  }

  config := &ssh.ClientConfig{
    User: "root",
    Auth: []ssh.AuthMethod{
      ssh.PublicKeys(signer),
    },
  }

  client, err := ssh.Dial("tcp", "hostname:22", config)
  
  if err != nil {
    panic("Failed to dial: " + err.Error())
  }

  // Each ClientConn can support multiple interactive sessions,
  // represented by a Session.
  session, err := client.NewSession()
  if err != nil {
    panic("Failed to create session: " + err.Error())
  }
  defer session.Close()

  // Once a Session is created, you can execute a single command on
  // the remote side using the Run method.
  var b bytes.Buffer
  session.Stdout = &b
  if err := session.Run("ls"); err != nil {
    panic("Failed to run: " + err.Error())
  }
  fmt.Println(b.String())
}

golang Golang RSA OAEP Decrypt

Golang RSA OAEP Decrypt

golang_rsa_oaep_decrypt.go
package main

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha1"
	"crypto/x509"
	"encoding/base64"
	"encoding/pem"
	"fmt"
)

//c# encrypted data
var encryptedData = `A1bZVqSMn983riamWR1ArGVOlMEllOjkCZVcmlyl9sgUYWr4ui1_g6XAfFi0EJrRsLeI2I2586x76fDN_8thT1jLcjdYcWDrcB24f7bgZ8iyRI2qMEJxYln4pkz3v5R07T7eG0sv1p5YNihObg48PzjIydaey5yM7vl8Cq1Hs-chz77qu6heObkyh6239WQgyRF3cqpLH_OPQ51fjTYI9zDfiptbAOJSE5WKDEArXLZxnb1NissiqOGdkpM9q4F7TRKzJ3RFxH5Gkcpx0A3xq8_HU7Z71O4Dv_emfjIcJyAJLWA4Ye831MVblcGYexcNzVqHQPmkJSfgl5GmQwyKbTevsggIMh9Jzhrbrg9En2zScnGMRsbJDC6zdoupr5EIXLfU`
var privateKeyData = `
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAygGoUiTD+LjwZIgwFZyjiibWNQ2LM9xZ2pjKQGP8iUBtAuAW
629/Ofw8qxToMyixPrG4A7j8+KOPwYrWPGV6Og//4zm3cG+1hQvnNUWtMjHHBY8O
ByUPQ6/T8XHER1DxFBfnWfFLZ1yFX6oNNuvtLgOreI6ehehJd5IB/4mOjMvFEBgO
Eejado2n55VNdcFpdQ3RcvGV+f/rl/lsIM08QvL3lc5gqawj53sW9YZi1DL/uN48
R+ghvAYhtx2jpHDBvlH1NCF1rU6CynYsgV9QIksv0ihwl4T+k5F9ir0uv0WIS6kK
KS1SRpAprRKunos4PlE8l2+jC6LaJUPhDZlj/wIDAQABAoIBAHIcX5YPeLie2AUi
PW9n7aYT7DtJ7FGebw+h8dZP5Q8vWqUeKzRR5p+90hOemtCTcxSEVfucWyKlWoat
Q/oYJOR5t0YHi40zPWnr4G7ibkUFg3Sra/QzRh0pTON+La9PlO+R1TmkqcC4rgrt
R8u3mGK+5fUTM49XOXEXBJPyg5kaXQpiA4BoIRdRnCSitNxWA8kxMkQYJYlwAYab
cKo4Ik/J6+YGG7m2FtrUAWpWVUMBzEYOmGJ7JhSJ1u0UC/Oh1HOS1xlGopkmexbd
EygY3hTNWzHmYaYcYQs0f+8aVcVL64Gm0dtqvAHNnBvudMThhQgdYPc39mNLbrwI
ks4uS8ECgYEA9XfvcGKsNrHA0nqoPUPMT0Nfvv/4XCaKOYk25brH4LbqJPm6CiU6
uNlKFQsxzHPmx7OEK7EYVVZCbSO9s4t/xCzDVNbOZ9kDL6bkTX9DArLE4d6IRF/1
WW/AlNPuwVgxl0kcJILFtLqA1WoC5UWMhbYe2YB/Q3rCozmn0AiwyqECgYEA0qxd
KClKAMIsrB0WJ9gZEsJOpFi4q4g6T1BwT40Xj6Ul6o6DHi6hFhPgZAstqmnY0ANz
ezQ2yxtIm7zSy7S+nwDUycjY9riJcomc/YQZNA2QVM16hEv84VLwH1MVV2wkTb41
DWjbcg/ZNofZHl9AQIw7es+R3mmtDN+8BZOZSp8CgYBHtwmaUQm1VQtbswAyHfuz
8KApgklCSvQ5SRBj38UDrw0LTnZ+/k+Ar+MH8ORUskvrblQgG7ZbQD9Z+YYzzX6/
hsBuqe9Vwb4/jsfGqHagdDA3OTegmlRpE9A06xInJKggZfi15gry+UYok7dS2pXq
fsHWk8capOP2oiKYEeHs4QKBgF2KcLaDVrtte/5Tz+GTHtbodZidWCm5jAJpeeSo
hfye3G4AJxHArH+sBacGG5md88mwrpbWwTl/fMbBmWsfbsAU02ZhCozJtSWpGo6q
F7K4DwzIS4zwXHEDrWCLOF+fwaLPQKkalM1ZYh3HRc0ph9LhMQu/nEn/6/laYhar
yZWLAoGASvCrpFKn0qllMKNUetBmYFpgtjmnNuW7l0xT2UftkW6AuFjU19gKgXhe
I+uZciHQ8kIUHfNLYBbhETsF3iqsklKfeoIr23zYHLE5GpoC151IpKf4guoPbCHX
a1oCDuZm//f5HMePb9juJN0WR//d5jWuizAycZf41XoEd8Bqydg=
-----END RSA PRIVATE KEY-----
`

func main() {
	//golang encrypted data
	encryptedData = `eE167RoMG0AgczAMUdaQ0581PRuCQA1_xNNkqiq-zR6y93YXz6hqqP-arAwGCcUySFqxvvgopVyWBABM5MBnhEGhUBvADae6EAwNWSFxm5buUBHFmHqYNrRWQaxO8F7QUZK1llctd_euoWixxAKCVIqnE0UsbcZEveULYgm3EVwbJTPUyfdRbX--lmDbsWHM2YEVuwL6f1jph_XrwKWUt62jbRnp21f7zPj2mWFZEUvCt_s6KfzymZRNky-0-QSKVI4IygZM2ZZ9gjjj7CXnrvpyTYc2_P86SHaYTP9ZhoOwdTixaRE60hnzZ5N1oUXYI99LD_-E6NziZxGoXg6qsA==`
	hash := sha1.New()
	random := rand.Reader
	privateKeyBlock, _ := pem.Decode([]byte(privateKeyData))
	var pri *rsa.PrivateKey
	pri, parseErr := x509.ParsePKCS1PrivateKey(privateKeyBlock.Bytes)
	if parseErr != nil {
		fmt.Println("Load private key error")
		panic(parseErr)
	}
	decodedData, _ := base64.URLEncoding.DecodeString(encryptedData)
	decryptedData, decryptErr := rsa.DecryptOAEP(hash, random, pri, decodedData, nil)
	if decryptErr != nil {
		fmt.Println("Decrypt data error")
		panic(decryptErr)
	}
	fmt.Println(string(decryptedData))
}

golang Golang RSA-OAEP加密和解密

Golang RSA-OAEP加密和解密

golang_rsa_oaep.go
package main

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha1"
	"crypto/x509"
	"encoding/base64"
	"encoding/pem"
	"fmt"
)

func main() {
	var publicKeyData = `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAygGoUiTD+LjwZIgwFZyj
iibWNQ2LM9xZ2pjKQGP8iUBtAuAW629/Ofw8qxToMyixPrG4A7j8+KOPwYrWPGV6
Og//4zm3cG+1hQvnNUWtMjHHBY8OByUPQ6/T8XHER1DxFBfnWfFLZ1yFX6oNNuvt
LgOreI6ehehJd5IB/4mOjMvFEBgOEejado2n55VNdcFpdQ3RcvGV+f/rl/lsIM08
QvL3lc5gqawj53sW9YZi1DL/uN48R+ghvAYhtx2jpHDBvlH1NCF1rU6CynYsgV9Q
Iksv0ihwl4T+k5F9ir0uv0WIS6kKKS1SRpAprRKunos4PlE8l2+jC6LaJUPhDZlj
/wIDAQAB
-----END PUBLIC KEY-----
`
	var privateKeyData = `
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAygGoUiTD+LjwZIgwFZyjiibWNQ2LM9xZ2pjKQGP8iUBtAuAW
629/Ofw8qxToMyixPrG4A7j8+KOPwYrWPGV6Og//4zm3cG+1hQvnNUWtMjHHBY8O
ByUPQ6/T8XHER1DxFBfnWfFLZ1yFX6oNNuvtLgOreI6ehehJd5IB/4mOjMvFEBgO
Eejado2n55VNdcFpdQ3RcvGV+f/rl/lsIM08QvL3lc5gqawj53sW9YZi1DL/uN48
R+ghvAYhtx2jpHDBvlH1NCF1rU6CynYsgV9QIksv0ihwl4T+k5F9ir0uv0WIS6kK
KS1SRpAprRKunos4PlE8l2+jC6LaJUPhDZlj/wIDAQABAoIBAHIcX5YPeLie2AUi
PW9n7aYT7DtJ7FGebw+h8dZP5Q8vWqUeKzRR5p+90hOemtCTcxSEVfucWyKlWoat
Q/oYJOR5t0YHi40zPWnr4G7ibkUFg3Sra/QzRh0pTON+La9PlO+R1TmkqcC4rgrt
R8u3mGK+5fUTM49XOXEXBJPyg5kaXQpiA4BoIRdRnCSitNxWA8kxMkQYJYlwAYab
cKo4Ik/J6+YGG7m2FtrUAWpWVUMBzEYOmGJ7JhSJ1u0UC/Oh1HOS1xlGopkmexbd
EygY3hTNWzHmYaYcYQs0f+8aVcVL64Gm0dtqvAHNnBvudMThhQgdYPc39mNLbrwI
ks4uS8ECgYEA9XfvcGKsNrHA0nqoPUPMT0Nfvv/4XCaKOYk25brH4LbqJPm6CiU6
uNlKFQsxzHPmx7OEK7EYVVZCbSO9s4t/xCzDVNbOZ9kDL6bkTX9DArLE4d6IRF/1
WW/AlNPuwVgxl0kcJILFtLqA1WoC5UWMhbYe2YB/Q3rCozmn0AiwyqECgYEA0qxd
KClKAMIsrB0WJ9gZEsJOpFi4q4g6T1BwT40Xj6Ul6o6DHi6hFhPgZAstqmnY0ANz
ezQ2yxtIm7zSy7S+nwDUycjY9riJcomc/YQZNA2QVM16hEv84VLwH1MVV2wkTb41
DWjbcg/ZNofZHl9AQIw7es+R3mmtDN+8BZOZSp8CgYBHtwmaUQm1VQtbswAyHfuz
8KApgklCSvQ5SRBj38UDrw0LTnZ+/k+Ar+MH8ORUskvrblQgG7ZbQD9Z+YYzzX6/
hsBuqe9Vwb4/jsfGqHagdDA3OTegmlRpE9A06xInJKggZfi15gry+UYok7dS2pXq
fsHWk8capOP2oiKYEeHs4QKBgF2KcLaDVrtte/5Tz+GTHtbodZidWCm5jAJpeeSo
hfye3G4AJxHArH+sBacGG5md88mwrpbWwTl/fMbBmWsfbsAU02ZhCozJtSWpGo6q
F7K4DwzIS4zwXHEDrWCLOF+fwaLPQKkalM1ZYh3HRc0ph9LhMQu/nEn/6/laYhar
yZWLAoGASvCrpFKn0qllMKNUetBmYFpgtjmnNuW7l0xT2UftkW6AuFjU19gKgXhe
I+uZciHQ8kIUHfNLYBbhETsF3iqsklKfeoIr23zYHLE5GpoC151IpKf4guoPbCHX
a1oCDuZm//f5HMePb9juJN0WR//d5jWuizAycZf41XoEd8Bqydg=
-----END RSA PRIVATE KEY-----
`
	pubKeyBlock, _ := pem.Decode([]byte(publicKeyData))
	hash := sha1.New()
	random := rand.Reader
	msg := []byte("helloworldjemyme")
	var pub *rsa.PublicKey
	pubInterface, parseErr := x509.ParsePKIXPublicKey(pubKeyBlock.Bytes)
	if parseErr != nil {
		fmt.Println("Load public key error")
		panic(parseErr)
	}
	pub = pubInterface.(*rsa.PublicKey)
	encryptedData, encryptErr := rsa.EncryptOAEP(hash, random, pub, msg, nil)
	if encryptErr != nil {
		fmt.Println("Encrypt data error")
		panic(encryptErr)
	}
	encodedData := base64.URLEncoding.EncodeToString(encryptedData)
	fmt.Println(encodedData)
	fmt.Println()
	fmt.Println("------I AM JUST A LINE------")
	fmt.Println()
	privateKeyBlock, _ := pem.Decode([]byte(privateKeyData))
	var pri *rsa.PrivateKey
	pri, parseErr = x509.ParsePKCS1PrivateKey(privateKeyBlock.Bytes)
	if parseErr != nil {
		fmt.Println("Load private key error")
		panic(parseErr)
	}
	decryptedData, decryptErr := rsa.DecryptOAEP(hash, random, pri, encryptedData, nil)
	if decryptErr != nil {
		fmt.Println("Decrypt data error")
		panic(decryptErr)
	}
	fmt.Println(string(decryptedData))
}

golang Lockfile使用PID文件

Lockfile使用PID文件

lock.go
// Handle pid file based locking.
package lockfile

import (
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"syscall"
)

type Lockfile string

var (
	ErrBusy        = errors.New("Locked by other process") // If you get this, retry after a short sleep might help
	ErrNeedAbsPath = errors.New("Lockfiles must be given as absolute path names")
	ErrInvalidPid  = errors.New("Lockfile contains invalid pid for system")
	ErrDeadOwner   = errors.New("Lockfile contains pid of process not existent on this system anymore")
)

// Describe a new filename located at path. It is expected to be an absolute path
func New(path string) (Lockfile, error) {
	if !filepath.IsAbs(path) {
		return Lockfile(""), ErrNeedAbsPath
	}
	return Lockfile(path), nil
}

// Who owns the lockfile?
func (l Lockfile) GetOwner() (*os.Process, error) {
	name := string(l)

	// Ok, see, if we have a stale lockfile here
	content, err := ioutil.ReadFile(name)
	if err != nil {
		return nil, err
	}

	var pid int
	_, err = fmt.Sscanln(string(content), &pid)
	if err != nil {
		return nil, ErrInvalidPid
	}

	// try hard for pids. If no pid, the lockfile is junk anyway and we delete it.
	if pid > 0 {
		p, err := os.FindProcess(pid)
		if err != nil {
			return nil, err
		}
		err = p.Signal(os.Signal(syscall.Signal(0)))
		if err == nil {
			return p, nil
		}
		errno, ok := err.(syscall.Errno)
		if !ok {
			return nil, err
		}

		switch errno {
		case syscall.ESRCH:
			return nil, ErrDeadOwner
		case syscall.EPERM:
			return p, nil
		default:
			return nil, err
		}
	} else {
		return nil, ErrInvalidPid
	}
	panic("Not reached")
}

// Try to get Lockfile lock. Returns nil, if successful and and error describing the reason, it didn't work out.
// Please note, that existing lockfiles containing pids of dead processes and lockfiles containing no pid at all
// are deleted.
func (l Lockfile) TryLock() error {
	name := string(l)

	// This has been checked by New already. If we trigger here,
	// the caller didn't use New and re-implemented it's functionality badly.
	// So panic, that he might find this easily during testing.
	if !filepath.IsAbs(string(name)) {
		panic(ErrNeedAbsPath)
	}

	tmplock, err := ioutil.TempFile(filepath.Dir(name), "")
	if err != nil {
		return err
	} else {
		defer tmplock.Close()
		defer os.Remove(tmplock.Name())
	}

	_, err = tmplock.WriteString(fmt.Sprintf("%d\n", os.Getpid()))
	if err != nil {
		return err
	}

	// return value intentionally ignored, as ignoring it is part of the algorithm
	_ = os.Link(tmplock.Name(), name)

	fiTmp, err := os.Lstat(tmplock.Name())
	if err != nil {
		return err
	}
	fiLock, err := os.Lstat(name)
	if err != nil {
		return err
	}

	// Success
	if os.SameFile(fiTmp, fiLock) {
		return nil
	}

	_, err = l.GetOwner()
	switch err {
	default:
		// Other errors -> defensively fail and let caller handle this
		return err
	case nil:
		return ErrBusy
	case ErrDeadOwner, ErrInvalidPid:
		// cases we can fix below
	}

	// clean stale/invalid lockfile
	err = os.Remove(name)
	if err != nil {
		return err
	}

	// now that we cleaned up the stale lockfile, let's recurse
	return l.TryLock()
}

// Release a lock again. Returns any error that happend during release of lock.
func (l Lockfile) Unlock() error {
	return os.Remove(string(l))
}