Skip to content

Instantly share code, notes, and snippets.

@sdvcrx
Created March 5, 2017 07:59
Show Gist options
  • Save sdvcrx/34d220f67c85c6f07b5a112147118af9 to your computer and use it in GitHub Desktop.
Save sdvcrx/34d220f67c85c6f07b5a112147118af9 to your computer and use it in GitHub Desktop.

fmt

%T: print type of variable

Slice

Usage

Create a slice:

sl1 := make([]string, 5);
sl2 := []int{1, 2, 3, 4, 5};

Append value to a slice:

sl1 = append(sl1, "string");
sl2 = append(sl2, 2, 3);
fmt.Println(len(sl2)); // 7

More

Map

Create a map:

m1 = make(map[string]int)
m1["key"] = 1

m2 = map[string]int{"str": 1}

Delete key from a map:

delete m1["key"]

Check key is exist in a map:

value, isExist = m1["key"]  // isExist = false

遍历map:

for key, value := range m2 {
  fmt.Printf("%s -> %d", key, value)
}

面向对象

Interface

定义:

type Human interface {
  walk()
}

只要某个对象与 Interface 有相同的函数签名,我们就可以说该对象实现了 XX 接口。

空Interface

空Interface即 interface{} 表示不包含任何 method ,即所有类型都实现该接口,相当于C语言中的 void *

Comma-ok assert

断言变量的类型是否为 T

value, ok = element.(T)
// element是interface{}对象
// T是断言的类型

More

http://jordanorelli.com/post/32665860244/how-to-use-interfaces-in-go

Reflect

反射即检查程序在运行时的状态。

并发

goroutine

go someFunc()

channel

默认情况下,channel 接收和发送数据都是阻塞的,除非另一端已经准备好,这样就使得Goroutines同步变的更加的简单,而不需要显式的lock。所谓阻塞,也就是如果读取(value := <-ch)它将会被阻塞,直到有数据接收。其次,任何发送(ch<-5)将会被阻塞,直到数据被读出。无缓冲 channel 是在多个 goroutine 之间同步很棒的工具。

func sum(a []int, c chan int) {
    total := 0
    for _, v := range a {
        total += v
    }
    c <- total  // send total to c
}

func main() {
    a := []int{7, 2, 8, -9, 4, 0}

    c := make(chan int)
    go sum(a[:len(a)/2], c)
    go sum(a[len(a)/2:], c)
    x, y := <-c, <-c  // 按顺序读取

    fmt.Println(x, y, x + y)
}

Buffered channel

channel默认无缓冲,故发送读取均会阻塞;如创建channel设定了buffer size,在buffer size以内可无阻塞写入。

func main() {
  c := make(chan int, 2)
  c <- 1
  c <- 2  // 无阻塞写入
  fmt.Println(<-c)
  fmt.Println(<-c)
}

Range和Close

可使用 range 读取 channel 中的数据。

func fibonacci(n int, c chan int) {
    x, y := 1, 1
    for i := 0; i < n; i++ {
        c <- x
        x, y = y, x + y
    }
    close(c)  // 必须在生产者中关闭channel!
}

func main() {
    c := make(chan int, 10)
    go fibonacci(cap(c), c)
    for i := range c {
        fmt.Println(i)
    }
}

Select

可用 select 来监听多个 channel

select默认是阻塞的,只有当监听的channel中有发送或接收可以进行时才会运行,当多个channel都准备好的时候,select是随机的选择一个执行的。

func doSomething(normal, quit chan int) {
  for {
    select {
    case normal <- 1:
      // do something
    case <- quit:  // quit channel 接收到数据后退出
      return // quit
    }
  }
}

Lib

io

io.Reader / io.Writer

type Reader interface {
    Read(p []byte) (n int, err error)
}

type Writer interface {
    Write(p []byte) (n int, err error)
}

io.Copy / io.CopyBuffer / io.CopyN

A successful Copy returns err == nil, not err == EOF.

r := strings.NewReader("some io.Reader stream to be read\n")

if _, err := io.Copy(os.Stdout, r); err != nil {
    log.Fatal(err)
}

CopyBuffer / CopyN:

func CopyBuffer(dst Writer, src Reader, buf []byte) (written int64, err error)
func CopyN(dst Writer, src Reader, n int64) (written int64, err error)

Copy buffer/n btyes from src to dst.

bufio

NewReader, NewWriter, NewScanner

io.Readerio.Writer io.Scanner 的简易封装

https://godoc.org/bufio#NewReadWriter

scanner.Split

You can custom scanner.Split func to control scan way

scanner scan reader by lines, if you want it to scan by words, see the following code:

const input = "123 3456 789"
scanner := bufio.NewScanner(strings.NewReader(input))
scanner.Split(bufio.ScanWords)
for scanner.Scan() {
  fmt.Println(scanner.Text())
}
// optional error handler
if err := scanner.Err(); err != nil {
  fmt.Println(err)
}

Custom split function:

const input = "1,2,3"

splitComma := func(data []byte, atEOF bool) (advance int, token []byte, err error) {
  for i := 0; i < len(data); i++ {
    if string(data[i]) == "," {
      return i + 1, data[:i], nil
    }
  }
  // return error if comma is not found
  return 0, data, bufio.ErrFinalToken
}

scanner.Split(splitComma)
scanner := bufio.NewScanner(strings.NewReader(input))
for scanner.Scan() {
  fmt.Println(scanner.Text())
  // output:
  // 1
  // 2
  // 3
}

time

Layout string: Mon Jan 2 15:04:05 MST 2006

即 星期一 一月二日下午三点四分五秒 2006年

t := time.Now()
t.Format("01-02 15:04:05")   // 01-15 21:34:54
t2, err := time.Parse("15 04", "22 41");  // 0000-01-01 22:41:00 +0000 UTC

t.AddDate(year, month, day)   // allow negative number
t.After(time) // check t is after `time` return boolean
t.Before(time)  // check t is before `time` return boolean

math/rand

math/rand 提供了伪随机数生成器。伪随机特性,种子不变,随机的结果就不会变。

rand.Intn(100)   // 81
rand.Intn(100)   // 87 重新运行程序也永远是这个数,伪随机特性,种子不变,随机的结果就不会变

自定义随机数种子:

source := rand.NewSource(time.Now().UnixNano())
rd := rand.New(source)

fmt.Printf("%d, %d", rd.Intn(100), rd.Intn(100))  // 重新运行程序结果改变,因为种子已经变化了

strconv

string to number:

val, err := strconv.Atoi("123")   // val => 123

net/http

Http处理流程:

http处理流程

Handler

create http.Handler :

type Handler interface {
    ServeHTTP(ResponseWriter, *Request)
}

or using http.HandleFunc :

func HandleFunc(pattern string, handler func(ResponseWriter, *Request))

第三方库

gorilla/mux - A powerful URL router and dispatcher for golang.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment