平时整理的一些golang代码片段

golang 代码片段

by boya
老司机请忽略!

  • 用chan实现斐波那契数列

    import "fmt"
    func fibonacci(c, quit chan int) {
    	x, y := 0, 1
    	for {
    		select {
    		case c <- x:
    			x, y = y, x+y
    		case <-quit:
    			fmt.Println("quit")
    			return
    		}
    	}
    }
    func main() {
    	c := make(chan int)
    	quit := make(chan int)
    	go func() {
    		for i := 0; i < 10; i++ {
    			fmt.Println(<-c)
    		}
    		quit <- 0
    	}()
    	fibonacci(c, quit)
    }
    
  • 字符串的简单映射

    func main() {
    	rot13 := func(r rune) rune {
    		switch {
    		case r >= 'A' && r <= 'Z':
    			return 'A' + (r-'A'+13)%26
    		case r >= 'a' && r <= 'z':
    			return 'a' + (r-'a'+13)%26
    		}
    		return r
    	}
    	fmt.Println(strings.Map(rot13, "'hello gopher..."))
    }
    
  • 利用chan做延时(超时)

    import "time"
    import "fmt"
    func main() {
    c1 := make(chan string, 1)
    go func() {
        time.Sleep(time.Second * 2)
        c1 <- "result 1"
    }()
    select {
    case res := <-c1:
        fmt.Println(res)
    case <-time.After(time.Second * 1):
        fmt.Println("timeout 1")
    }
    }
    
  • 利用闭包输出递增整数的平方

    func squares() func() int {
    var x int
    return func() int {
        x++
        return x * x
    }
    }
    func main() {
    f := squares()
    fmt.Println(f()) // "1"
    fmt.Println(f()) // "4"
    fmt.Println(f()) // "9"
    fmt.Println(f()) // "16"
    }
    
  • 统计整数包含多少个值为1的2进制数

    package main
    
    // pc[i] is the population count of i.
    var pc [256]byte
    
    func init() {
    	for i := range pc {
    		pc[i] = pc[i/2] + byte(i&1)
    	}
    
    }
    
    // PopCount returns the population count (number of set bits) of x.
    func PopCount(x uint64) int {
    	return int(pc[byte(x>>(0*8))] +
    		pc[byte(x>>(1*8))] +
    		pc[byte(x>>(2*8))] +
    		pc[byte(x>>(3*8))] +
    		pc[byte(x>>(4*8))] +
    		pc[byte(x>>(5*8))] +
    		pc[byte(x>>(6*8))] +
    		pc[byte(x>>(7*8))])
    }
    
    func main() {
    	println(PopCount(9))
    }
    
  • 常量生成器

    const (
    _ = 1 << (10 * iota)
    KiB // 1024
    MiB // 1048576
    GiB // 1073741824
    TiB // 1099511627776             (exceeds 1 << 32)
    PiB // 1125899906842624
    EiB // 1152921504606846976
    ZiB // 1180591620717411303424    (exceeds 1 << 64)
    YiB // 1208925819614629174706176
    )
    
  • 二叉树和利用二叉树排序

    package main
    
    import "fmt"
    
    type tree struct {
    	value       int
    	left, right *tree
    }
    
    func Sort(values []int) {
    	var root *tree
    	for _, v := range values {
    		root = add(root, v)
    	}
    	appendValues(values[:0], root)
    }
    
    func appendValues(values []int, t *tree) []int {
    	if t != nil {
    		values = appendValues(values, t.left)
    		values = append(values, t.value)
    		values = appendValues(values, t.right)
    	}
    	return values
    }
    
    func add(t *tree, value int) *tree {
    	if t == nil {
    		t = new(tree)
    		t.value = value
    		return t
    	}
    	if value < t.value {
    		t.left = add(t.left, value)
    	} else {
    		t.right = add(t.right, value)
    	}
    	return t
    }
    
    func main() {
    	data := []int{1, 5, 6, 3, 2, 7, 8, 9}
    	Sort(data)
    	fmt.Println(data)
    }
    
  • 通过方法表达式来操作选用哪个方法

    type Point struct{ X, Y float64 }
    
    func (p Point) Add(q Point) Point { return Point{p.X + q.X, p.Y + q.Y} }
    func (p Point) Sub(q Point) Point { return Point{p.X - q.X, p.Y - q.Y} }
    
    type Path []Point
    
    func (path Path) TranslateBy(offset Point, add bool) {
    var op func(p, q Point) Point
    if add {
        op = Point.Add
    } else {
        op = Point.Sub
    }
    for i := range path {
        // Call either path[i].Add(offset) or path[i].Sub(offset).
        path[i] = op(path[i], offset)
    }
    }
    
  • interface的类型断言

    func sqlQuote(x interface{}) string {
    switch x := x.(type) {
    case nil:
        return "NULL"
    case int, uint:
        return fmt.Sprintf("%d", x) // x has type interface{} here.
    case bool:
        if x {
            return "TRUE"
        }
        return "FALSE"
    case string:
        return sqlQuoteString(x) // (not shown)
    default:
        panic(fmt.Sprintf("unexpected type %T: %v", x, x))
    }
    }
    
  • ch这个channel的buffer大小是1,所以会交替的为空或为满,所以只有一个case可以进行下去,无论i是奇数或者偶数,它都会打印0 2 4 6 8

    ch := make(chan int, 1)
    for i := 0; i < 10; i++ {
    select {
    case x := <-ch:
        fmt.Println(x) // "0" "2" "4" "6" "8"
    case ch <- i:
    }
    }
    
  • 用const 表示字符格式

    const template = `Warning: you are using %d bytes of  storage,%d%% of your quota.`
    
  • 反射

    func main() {
    hl := hello
    fv := reflect.ValueOf(hl)
    fmt.Println("fv is reflect.Func ?",fv.Kind() == reflect.Func)
    fv.Call(nil)
    }
    
  • 变长参数

    func (engine *Engine) Use(middleware ...HandlerFunc) IRoutes {
    	engine.RouterGroup.Use(middleware...)
    	engine.rebuild404Handlers()
    	engine.rebuild405Handlers()
    	return engine
    }
    
  • 心跳包的简单实现

    func worker(start chan bool) {
        heartbeat := time.Tick(30 * time.Second)
        for {
                select {
                     // … do some stuff
                case <- heartbeat:
                    //… do heartbeat stuff
                }
        }
    }
    
  • 删除某个slice的某个元素

    for i := range s {
    if equal(s[i], element) {
    	s = append(s[:i], s[i+1:]...)
    }
    }
    
  • 把数组转slice

    func main() { 
    a := [3]int{1, 2, 3} 
    b := a[:] 
    fmt.Println(b) 
    } 
    func main(){
    a := [3]int{1, 2, 3}
    b := (&a)[:]
    }
    
  • 数据转发

    func forward(src net.Conn, network, address string, timeout time.Duration) {
    	defer src.Close()
    	dst, err := net.DialTimeout(network, address, timeout)
    	if err != nil {
    		log.Printf("dial err: %s", err)
    		return
    	}
    	defer dst.Close()
    
    	cpErr := make(chan error)
    
    	go cp(cpErr, src, dst)
    	go cp(cpErr, dst, src)
    
    	select {
    	case err = <-cpErr:
    		if err != nil {
    			log.Printf("copy err: %v", err)
    		}
    	}
    
    	log.Printf("disconnect: %s", src.RemoteAddr())
    }
    
    func cp(c chan error, w io.Writer, r io.Reader) {
    	_, err := io.Copy(w, r)
    	c <- err
    	fmt.Println("cp end")
    }
    
  • 获取当前目录和父级目录

    func substr(s string, pos, length int) string {
    	runes := []rune(s)
    	l := pos + length
    	if l > len(runes) {
    		l = len(runes)
    	}
    	return string(runes[pos:l])
    }
    
    func getParentDirectory(dirctory string) string {
    	return substr(dirctory, 0, strings.LastIndex(dirctory, "/"))
    }
    
    func getCurrentDirectory() string {
    	dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
    	if err != nil {
    		log.Fatal(err)
    	}
    	return strings.Replace(dir, "\\", "/", -1)
    }
    
  • 保存当前程序的pid

    func savePid() {
    	pidFilename := ROOT + "/pid/" +filepath.Base(os.Args[0]) + ".pid"
    	pid := os.Getpid()
    
    	ioutil.WriteFile(pidFilename, []byte(strconv.Itoa(pid)), 0755)
    }
    
  • 利用struct{}当channel

    ch:=make(chan struct{})
    ch <- struct{}{}
    <-ch
    
  • break加label

    OuterLoop:
    	for i = 0; i < n; i++ {
    		for j = 0; j < m; j++ {
    			switch a[i][j] {
    			case nil:
    				state = Error
    				break OuterLoop
    			case item:
    				state = Found
    				break OuterLoop
    			}
    		}
    	}
    
  • Go语言实现http共享文件服务器

    package main  
    import (  
            "net/http"  
            "os"  
            "strings"  
    )  
    func shareDir(dirName string,port string,ch chan bool){  
            h := http.FileServer(http.Dir(dirName))  
            err := http.ListenAndServe(":"+port,h)  
            if err != nil {  
                    println("ListenAndServe : ",err.Error())  
                    ch <- false  
            }  
    }  
    func main(){  
            ch := make(chanbool)  
            port := "8000"//Default port  
            iflen(os.Args)>1 {  
                    port = strings.Join(os.Args[1:2],"")  
            }  
            go shareDir(".",port,ch)  
            println("Listening on port ",port,"...")  
            bresult := <-ch  
            iffalse == bresult {  
                    println("Listening on port ",port," failed")  
            }  
    }  
        
    
  • 简单的TCP代理服务器

    package main
    
    import (
    	"fmt"
    	"io"
    	"net"
    	"os"
    )
    
    func main() {
    	if len(os.Args) != 3 {
    		fatal("usage: netfwd localIp:localPort remoteIp:remotePort")
    	}
    	localAddr := os.Args[1]
    	remoteAddr := os.Args[2]
    	local, err := net.Listen("tcp", localAddr)
    	if local == nil {
    		fatal("cannot listen: %v", err)
    	}
    	for {
    		conn, err := local.Accept()
    		if conn == nil {
    			fatal("accept failed: %v", err)
    		}
    		go forward(conn, remoteAddr)
    	}
    }
    
    func forward(local net.Conn, remoteAddr string) {
    	remote, err := net.Dial("tcp", remoteAddr)
    	if remote == nil {
    		fmt.Fprintf(os.Stderr, "remote dial failed: %v\n", err)
    		return
    	}
    	go io.Copy(local, remote)
    	go io.Copy(remote, local)
    }
    
    func fatal(s string, a ...interface{}) {
    	fmt.Fprintf(os.Stderr, "netfwd: %s\n", fmt.Sprintf(s, a))
    	os.Exit(2)
    }
    
    
  • 选择排序是不稳定的。算法复杂度是O(n ^2 )。

    package main
    import (    
    "fmt"
    )
    
    type SortInterface interface {
    sort()
    }
    type Sortor struct {
    name string
    }
    
    func main() {
    arry := []int{6, 1, 3, 5, 8, 4, 2, 0, 9, 7}
    learnsort := Sortor{name: "选择排序--从小到大--不稳定--n*n---"}
    learnsort.sort(arry)
    fmt.Println(learnsort.name, arry)
    }
    
    func (sorter Sortor) sort(arry []int) {
    arrylength := len(arry)    for i := 0; i < arrylength; i++ {
        min := i        for j := i + 1; j < arrylength; j++ {            if arry[j] < arry[min] {
                min = j
            }
        }
        t := arry[i]
        arry[i] = arry[min]
        arry[min] = t
    
    }
    }
    
    http://blog.csdn.net/guoer9973/article/details/51924715
    
  • 检查文件或目录是否存在

    // 如果由 filename 指定的文件或目录存在则返回 true,否则返回 false
    func fileExist(filename string) bool {
    _, err := os.Stat(filename)
    return err == nil || os.IsExist(err)
    }
    
  • 重定向golang的panic信息

    package main
    
    import (
    "log"
    "os"
    "syscall"
    )
    
    // redirectStderr to the file passed in
    func redirectStderr(f *os.File) {
    err := syscall.Dup2(int(f.Fd()), int(os.Stderr.Fd()))
    if err != nil {
        log.Fatalf("Failed to redirect stderr to file: %v", err)
    }
    }
    
    import (
    	"code.google.com/p/log4go"
    	"os"
    	"syscall"
    )
    
    var (
    	kernel32         = syscall.MustLoadDLL("kernel32.dll")
    	procSetStdHandle = kernel32.MustFindProc("SetStdHandle")
    )
    
    func SetStdHandle(stdhandle int32, handle syscall.Handle) error {
    	r0, _, e1 := syscall.Syscall(procSetStdHandle.Addr(), 2, uintptr(stdhandle), uintptr(handle), 0)
    	if r0 == 0 {
    		if e1 != 0 {
    			return error(e1)
    		}
    		return syscall.EINVAL
    	}
    	return nil
    }
    
    var f *os.File
    
    func redirect_err() {
    	var err error
    	f, err = os.Create(`panic.txt`)
    	if err != nil {
    		log4go.Error("os.Create failed: %v", err)
    	}
    	err = SetStdHandle(syscall.STD_ERROR_HANDLE, syscall.Handle(f.Fd()))
    	if err != nil {
    		log4go.Error("SetStdHandle failed: %v", err)
    	}
    }
    
  • go 执行命令并获取stderr

    var stderr io.ReadCloser
    cmd := exec.Command("ping", 
        "localhost"
    )
    stderr, err = cmd.StderrPipe()
    	if err != nil {
    		glog.Errorln("stderr pipe error: ", err)
    	}
    	// start cmd
    	err = cmd.Start()
    	if err != nil {
    		glog.Infoln("start cmd error: ", err)
    		return err
    	}
    
    	glog.Infoln("start ", cmd.Args)
    	if stderr != nil {
    		reader := bufio.NewReader(stderr)
    		go func() {
    			for {
    				line, err := reader.ReadString(byte('\n'))
    				if err != nil || io.EOF == err {
    					glog.Infoln("cmd end")
    					stderr.Close()
    					break
    				}
    				glog.Infoln("stderr: ", line)
    			}
    		}()
    	}
    	err:=cmd.Wait()
    	if err!=nil {
    	    return err
    	}
    
  • 判断accept是不是临时错误

    for {
    conn,err:=ln.Accept()
    if err, ok := err.(net.Error); ok && err.Temporary() {
        continue
    }
    }
    
  • 快速遍历当前文件夹和文件

    package main
    
    import (
    	"fmt"
    	"path/filepath"
    )
    
    func main() {
    	upperDirPattern := "./*"
    	matches, err := filepath.Glob(upperDirPattern)
    	if err != nil {
    		panic(err)
    	}
    	for _, file := range matches {
    		fmt.Println(file)
    	}
    }
    
Go 
comments powered by Disqus