Golang官方教程A Tour of Go

参考文档

Go Playground

官方网站

vimeo

beego

A Tour of Go

In Depth Learning

Go On Github

defer命令

1. Fibonacci implemention

This fibonacci is implemented with function closure, anonymous function and defer. It is a perfect example for these features.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package main

import "fmt"

// fibonacci is a function that returns
// a function that returns an int.
func fibonacci() func() int {
current:=1
last:=0
return func()int{
defer func(){
current, last = last+current, current
}()

return last
}
}

func main() {
f := fibonacci()
for i := 0; i < 10; i++ {
fmt.Println(f())
}
}


2. Function closure


3. Anonymous func

  • 匿名方法

    1
    2
    3
    4
    5
    6
    7
    package main

    import "fmt"

    func main(){
    func () {fmt.Println("Hello world!")}()
    }
  • 带参数和返回值的匿名方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    package main

    import "fmt"

    func main() {
    a := func(i int)int {
    i++
    fmt.Println("Hello world!", i)
    return i
    }(1)

    fmt.Println(a)
    }

4. defer

The behavior of defer statements is straightforward and predictable. There are three simple rules:

4.1 A deferred function’s arguments are evaluated when the defer statement is evaluated.
1
2
3
4
5
6
func a() {
i := 0
defer fmt.Println(i)
i++
return
}
4.2 Deferred function calls are executed in Last In First Out order after the surrounding function returns.
1
2
3
4
5
6
7
8
func b(){
fmt.Println("function started:------------- revsed")
for i:=0;i<10;i++{
defer fmt.Println(i)
}
fmt.Println("function completed!")
a()
}
4.3 Deferred functions may read and assign to the returning function’s named return values.
1
2



5. channels

Channels are a typed conduit through which you can send and receive values with the channel operator, <-.

1
ch <- value // send value to channel


6. 指针

  • Go有指针, 然而没有指针运算(不能通过指针遍历字符串), 因此它更像是引用, 而不是C语言中的指针. 例如, p++ 表示(p)++,而不是C语言中指针的含义.
  • Go中调用函数的时候, 变量是值传递的.
  • 因此, 为了修改一个传入函数的值得效率和可能性, 有了指针.

7. 内存分配:new, make

Go有两个内存分配原语: new和make

  • new : new(T)分配了零值填充的T类型的内存空间, 并且返回一个指针(*T类型的值), 指向新分配的类型T的零值.
  • make : make只能创建slice, map和channel, 并且返回一个有初始值(非零)的T类型, 而不是T*
    1
    2
    var p *[]int = new([]int) //分配slice结构内存, 很少使用
    var v []int = make([]int,100)//一个新分配的有100个整数的数组

8. 定义自己的类型

  • 创建一个新的类型foo作用跟int一样

    1
    type foo int
  • 创建更复杂的类型需要用struct关键字

    1
    2
    3
    4
    type NameAge struct{
    name string
    age int
    }

9. Proxy For IntelliJ Idea

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package main

// Go语言实现简单的反向代理工具 for idea
//https://www.imsxm.com/2017/12/go-active-proxy-tool.html

import (
"flag"
"log"
"net/http"
"net/http/httputil"
"net/url"
)

type handle struct{ reverseProxy string }

/**反向代理**/
func (this *handle) ServeHTTP(w http.ResponseWriter, r *http.Request) {
remote, err := url.Parse(this.reverseProxy)
if err != nil {
log.Fatalln(err)
}
proxy := httputil.NewSingleHostReverseProxy(remote)
r.Host = remote.Host
proxy.ServeHTTP(w, r)
log.Println(r.RemoteAddr + " " + r.Method + " " + r.URL.String() + " " + r.Proto + " " + r.UserAgent())
}

func main() {
bind := flag.String("l", "0.0.0.0:8888", "listen on ip:port")
remote := flag.String("r", "http://idea.imsxm.com:80", "reverse proxy addr")
flag.Parse()
log.Printf("Listening on %s, forwarding to %s", *bind, *remote)
h := &handle{reverseProxy: *remote}
err := http.ListenAndServe(*bind, h)
if err != nil {
log.Fatalln("ListenAndServe: ", err)
}
}