目录 []
初级
开大括号不能放在单独的一行
未使用的变量
未使用的 Imports
简式的变量声明仅可以在函数内部使用
使用简式声明重复声明变量
偶然的变量隐藏 Accidental Variable Shadowing
不使用显式类型, 无法使用 "nil" 来初始化变量
使用 "nil" Slices and Maps
Map 的容量
字符串不会为 nil
Array 函数的参数
在 Slice 和 Array 使用 "range" 语句时的出现的不希望得到的值
Slices 和 Arrays 是一维的
访问不存在的 Map Keys
Strings 无法修改
String 和 Byte Slice 之间的转换
String 和索引操作
字符串不总是 UTF8 文本
字符串的长度
在多行的 Slice,Array 和 Map 语句中遗漏逗号
log.Fatal 和 log.Panic 不仅仅是 Log
内建的数据结构操作不是同步的
String 在 "range" 语句中的迭代值
对 Map 使用 "for range" 语句迭代
"switch" 声明中的失效行为
自增和自减
按位 NOT 操作
操作优先级的差异
未导出的结构体不会被编码
有活动的 Goroutines 下的应用退出
向无缓存的 Channel 发送消息, 只要目标接收者准备好就会立即返回
向已关闭的 Channel 发送会引起 Panic
使用 "nil" Channels
传值方法的接收者无法修改原有的值
中级
关闭 HTTP 的响应
关闭 HTTP 的连接
比较 Structs, Arrays, Slices, and Maps
从 Panic 中恢复
在 Slice, Array, and Map "range" 语句中更新引用元素的值
在 Slice 中 "隐藏" 数据
Slice 的数据 "毁坏"
陈旧的(Stale)Slices
类型声明和方法
从 "for switch" 和 "for select" 代码块中跳出
"for" 声明中的迭代变量和闭包
Defer 函数调用参数的求值
被 Defer 的函数调用执行
失败的类型断言
阻塞的 Goroutine 和资源泄露
高级
使用指针接收方法的值的实例
更新 Map 的值
"nil" Interfaces 和 "nil" Interfaces 的值
栈和堆变量
GOMAXPROCS, 并发, 和并行
读写操作的重排顺序
优先调度
- package main
- import "fmt"
- func main()
- { //error, can't have the opening brace on a separate line
- fmt.Println("hello there!")
- }
- package main
- import "fmt"
- func main() {
- fmt.Println("works!")
- }
- Fails:
- package main
- var gvar int //not an error
- func main() {
- var one int //error, unused variable
- two := 2 //error, unused variable
- var three int //error, even though it's assigned 3 on the next line
- three = 3
- }
- Compile Errors:
- /tmp/sandbox473116179/main.go:6: one declared and not used
- /tmp/sandbox473116179/main.go:7: two declared and not used
- /tmp/sandbox473116179/main.go:8: three declared and not used
- Works:
- package main
- import "fmt"
- func main() {
- var one int
- _ = one
- two := 2
- fmt.Println(two)
- var three int
- three = 3
- one = three
- var four int
- four = four
- }
- Fails:
- package main
- import (
- "fmt"
- "log"
- "time"
- )
- func main() {
- }
- Compile Errors:
- /tmp/sandbox627475386/main.go:4: imported and not used: "fmt"
- /tmp/sandbox627475386/main.go:5: imported and not used: "log"
- /tmp/sandbox627475386/main.go:6: imported and not used: "time"
- Works:
- package main
- import (
- _ "fmt"
- "log"
- "time"
- )
- var _ = log.Println
- func main() {
- _ = time.Now
- }
- Fails:
- package main
- myvar := 1 //error
- func main() {
- }
- Compile Error:
- /tmp/sandbox265716165/main.go:3: non-declaration statement outside function body
- Works:
- package main
- var myvar = 1
- func main() {
- }
- Fails:
- package main
- func main() {
- one := 0
- one := 1 //error
- }
- Compile Error:
- /tmp/sandbox706333626/main.go:5: no new variables on left side of :=
- Works:
- package main
- func main() {
- one := 0
- one, two := 1,2
- one,two = two,one
- }
- package main
- import "fmt"
- func main() {
- x := 1
- fmt.Println(x) //prints 1
- {
- fmt.Println(x) //prints 1
- x := 2
- fmt.Println(x) //prints 2
- }
- fmt.Println(x) //prints 1 (bad if you need 2)
- }
- go tool vet -shadow your_file.go
- .
- Fails:
- package main
- func main() {
- var x = nil //error
- _ = x
- }
- Compile Error:
- /tmp/sandbox188239583/main.go:4: use of untyped nil
- Works:
- package main
- func main() {
- var x interface{} = nil
- _ = x
- }
- Works:
- package main
- func main() {
- var s []int
- s = append(s,1)
- }
- Fails:
- package main
- func main() {
- var m map[string]int
- m["one"] = 1 //error
- }
- Fails:
- package main
- func main() {
- m := make(map[string]int,99)
- cap(m) //error
- }
- Compile Error:
- /tmp/sandbox326543983/main.go:5: invalid argument m (type map[string]int) for cap
- Fails:
- package main
- func main() {
- var x string = nil //error
- if x == nil { //error
- x = "default"
- }
- }
- Compile Errors:
- /tmp/sandbox630560459/main.go:4: cannot use nil as type string in assignment /tmp/sandbox630560459/main.go:6: invalid operation: x == nil (mismatched types string and nil)
- Works:
- package main
- func main() {
- var x string //defaults to "" (zero value)
- if x == "" {
- x = "default"
- }
- }
- package main
- import "fmt"
- func main() {
- x := [3]int{1,2,3}
- func(arr [3]int) {
- arr[0] = 7
- fmt.Println(arr) //prints [7 2 3]
- }(x)
- fmt.Println(x) //prints [1 2 3] (not ok if you need [7 2 3])
- }
- package main
- import "fmt"
- func main() {
- x := [3]int{1,2,3}
- func(arr *[3]int) {
- (*arr)[0] = 7
- fmt.Println(arr) //prints &[7 2 3]
- }(&x)
- fmt.Println(x) //prints [7 2 3]
- }
- package main
- import "fmt"
- func main() {
- x := []int{1,2,3}
- func(arr []int) {
- arr[0] = 7
- fmt.Println(arr) //prints [7 2 3]
- }(x)
- fmt.Println(x) //prints [7 2 3]
- }
- Bad:
- package main
- import "fmt"
- func main() {
- x := []string{"a","b","c"}
- for v := range x {
- fmt.Println(v) //prints 0, 1, 2
- }
- }
- Good:
- package main
- import "fmt"
- func main() {
- x := []string{"a","b","c"}
- for _, v := range x {
- fmt.Println(v) //prints a, b, c
- }
- }
- package main
- func main() {
- x := 2
- y := 4
- table := make([][]int,x)
- for i:= range table {
- table[i] = make([]int,y)
- }
- }
- package main
- import "fmt"
- func main() {
- h, w := 2, 4
- raw := make([]int,h*w)
- for i := range raw {
- raw[i] = i
- }
- fmt.Println(raw,&raw[4])
- //prints: [0 1 2 3 4 5 6 7] <ptr_addr_x>
- table := make([][]int,h)
- for i:= range table {
- table[i] = raw[i*w:i*w + w]
- }
- fmt.Println(table,&table[1][0])
- //prints: [[0 1 2 3] [4 5 6 7]] <ptr_addr_x>
- }
- Bad:
- package main
- import "fmt"
- func main() {
- x := map[string]string{"one":"a","two":"","three":"c"}
- if v := x["two"]; v == "" { //incorrect
- fmt.Println("no entry")
- }
- }
- Good:
- package main
- import "fmt"
- func main() {
- x := map[string]string{"one":"a","two":"","three":"c"}
- if _,ok := x["two"]; !ok {
- fmt.Println("no entry")
- }
- }
- Fails:
- package main
- import "fmt"
- func main() {
- x := "text"
- x[0] = 'T'
- fmt.Println(x)
- }
- Compile Error:
- /tmp/sandbox305565531/main.go:7: cannot assign to x[0]
- Works:
- package main
- import "fmt"
- func main() {
- x := "text"
- xbytes := []byte(x)
- xbytes[0] = 'T'
- fmt.Println(string(xbytes)) //prints Text
- }
- for i,v := range []byte(str) {...}
- .
- package main
- import "fmt"
- func main() {
- x := "text"
- fmt.Println(x[0]) //print 116
- fmt.Printf("%T",x[0]) //prints uint8
- }
- package main
- import (
- "fmt"
- "unicode/utf8"
- )
- func main() {
- data1 := "ABC"
- fmt.Println(utf8.ValidString(data1)) //prints: true
- data2 := "A\xfeC"
- fmt.Println(utf8.ValidString(data2)) //prints: false
- }
- data = u''
- print(len(data)) #prints: 1
- package main
- import "fmt"
- func main() {
- data := ""
- fmt.Println(len(data)) //prints: 3
- }
- package main
- import (
- "fmt"
- "unicode/utf8"
- )
- func main() {
- data := ""
- fmt.Println(utf8.RuneCountInString(data)) //prints: 1
- }
- package main
- import (
- "fmt"
- "unicode/utf8"
- )
- func main() {
- data := "é"
- fmt.Println(len(data)) //prints: 3
- fmt.Println(utf8.RuneCountInString(data)) //prints: 2
- }
- Fails:
- package main
- func main() {
- x := []int{
- 1,
- 2 //error
- }
- _ = x
- }
- Compile Errors:
- /tmp/sandbox367520156/main.go:6: syntax error: need trailing comma before newline in composite literal /tmp/sandbox367520156/main.go:8: non-declaration statement outside function body /tmp/sandbox367520156/main.go:9: syntax error: unexpected }
- Works:
- package main
- func main() {
- x := []int{
- 1,
- 2,
- }
- x = x
- y := []int{3,4,} //no error
- y = y
- }
- package main
- import "log"
- func main() {
- log.Fatalln("Fatal Level: log entry") //app exits here
- log.Println("Normal Level: log entry")
- }
- package main
- import "fmt"
- func main() {
- data := "A\xfe\x02\xff\x04"
- for _,v := range data {
- fmt.Printf("%#x",v)
- }
- //prints: 0x41 0xfffd 0x2 0xfffd 0x4 (not ok)
- fmt.Println()
- for _,v := range []byte(data) {
- fmt.Printf("%#x",v)
- }
- //prints: 0x41 0xfe 0x2 0xff 0x4 (good)
- }
- package main
- import "fmt"
- func main() {
- m := map[string]int{"one":1,"two":2,"three":3,"four":4}
- for k,v := range m {
- fmt.Println(k,v)
- }
- }
- package main
- import "fmt"
- func main() {
- isSpace := func(ch byte) bool {
- switch(ch) {
- case ' ': //error
- case '\t':
- return true
- }
- return false
- }
- fmt.Println(isSpace('\t')) //prints true (ok)
- fmt.Println(isSpace(' ')) //prints false (not ok)
- }
- package main
- import "fmt"
- func main() {
- isSpace := func(ch byte) bool {
- switch(ch) {
- case '','\t':
- return true
- }
- return false
- }
- fmt.Println(isSpace('\t')) //prints true (ok)
- fmt.Println(isSpace(' ')) //prints true (ok)
- }
- Fails:
- package main
- import "fmt"
- func main() {
- data := []int{1,2,3}
- i := 0
- ++i //error
- fmt.Println(data[i++]) //error
- }
- Compile Errors:
- /tmp/sandbox101231828/main.go:8: syntax error: unexpected ++ /tmp/sandbox101231828/main.go:9: syntax error: unexpected ++, expecting :
- Works:
- package main
- import "fmt"
- func main() {
- data := []int{1,2,3}
- i := 0
- i++
- fmt.Println(data[i])
- }
- Fails:
- package main
- import "fmt"
- func main() {
- fmt.Println(~2) //error
- }
- Compile Error:
- /tmp/sandbox965529189/main.go:6: the bitwise complement operator is ^
- Works:
- package main
- import "fmt"
- func main() {
- var d uint8 = 2
- fmt.Printf("%08b\n",^d)
- }
- package main
- import "fmt"
- func main() {
- var a uint8 = 0x82
- var b uint8 = 0x02
- fmt.Printf("%08b [A]\n",a)
- fmt.Printf("%08b [B]\n",b)
- fmt.Printf("%08b (NOT B)\n",^b)
- fmt.Printf("%08b ^ %08b = %08b [B XOR 0xff]\n",b,0xff,b ^ 0xff)
- fmt.Printf("%08b ^ %08b = %08b [A XOR B]\n",a,b,a ^ b)
- fmt.Printf("%08b & %08b = %08b [A AND B]\n",a,b,a & b)
- fmt.Printf("%08b &^%08b = %08b [A'AND NOT'B]\n",a,b,a &^ b)
- fmt.Printf("%08b&(^%08b)= %08b [A AND (NOT B)]\n",a,b,a & (^b))
- }
- package main
- import "fmt"
- func main() {
- fmt.Printf("0x2 & 0x2 + 0x4 -> %#x\n",0x2 & 0x2 + 0x4)
- //prints: 0x2 & 0x2 + 0x4 -> 0x6
- //Go: (0x2 & 0x2) + 0x4
- //C++: 0x2 & (0x2 + 0x4) -> 0x2
- fmt.Printf("0x2 + 0x2 <<0x1 -> %#x\n",0x2 + 0x2 <<0x1)
- //prints: 0x2 + 0x2 << 0x1 -> 0x6
- //Go: 0x2 + (0x2 <<0x1)
- //C++: (0x2 + 0x2) << 0x1 -> 0x8
- fmt.Printf("0xf | 0x2 ^ 0x2 -> %#x\n",0xf | 0x2 ^ 0x2)
- //prints: 0xf | 0x2 ^ 0x2 -> 0xd
- //Go: (0xf | 0x2) ^ 0x2
- //C++: 0xf | (0x2 ^ 0x2) -> 0xf
- }
- Fails:
- package main
- import (
- "fmt"
- "encoding/json"
- )
- type MyData struct {
- One int
- two string
- }
- func main() {
- in := MyData{1,"two"}
- fmt.Printf("%#v\n",in) //prints main.MyData{One:1, two:"two"}
- encoded,_ := json.Marshal(in)
- fmt.Println(string(encoded)) //prints {"One":1}
- var out MyData
- json.Unmarshal(encoded,&out)
- fmt.Printf("%#v\n",out) //prints main.MyData{One:1, two:""}
- }
- package main
- import (
- "fmt"
- "time"
- )
- func main() {
- workerCount := 2
- for i := 0; i <workerCount; i++ {
- go doit(i)
- }
- time.Sleep(1 * time.Second)
- fmt.Println("all done!")
- }
- func doit(workerId int) {
- fmt.Printf("[%v] is running\n",workerId)
- time.Sleep(3 * time.Second)
- fmt.Printf("[%v] is done\n",workerId)
- }
- [0] is running
- [1] is running
- all done!
- package main
- import (
- "fmt"
- "sync"
- )
- func main() {
- var wg sync.WaitGroup
- done := make(chan struct{})
- workerCount := 2
- for i := 0; i < workerCount; i++ {
- wg.Add(1)
- go doit(i,done,wg)
- }
- close(done)
- wg.Wait()
- fmt.Println("all done!")
- }
- func doit(workerId int,done <-chan struct{},wg sync.WaitGroup) {
- fmt.Printf("[%v] is running\n",workerId)
- defer wg.Done()
- <- done
- fmt.Printf("[%v] is done\n",workerId)
- }
- [0] is running
- [0] is done
- [1] is running
- [1] is done
- package main
- import (
- "fmt"
- "sync"
- )
- func main() {
- var wg sync.WaitGroup
- done := make(chan struct{})
- wq := make(chan interface{})
- workerCount := 2
- for i := 0; i < workerCount; i++ {
- wg.Add(1)
- go doit(i,wq,done,&wg)
- }
- for i := 0; i < workerCount; i++ {
- wq <- i
- }
- close(done)
- wg.Wait()
- fmt.Println("all done!")
- }
- func doit(workerId int, wq <-chan interface{},done <-chan struct{},wg *sync.WaitGroup) {
- fmt.Printf("[%v] is running\n",workerId)
- defer wg.Done()
- for {
- select {
- case m := <- wq:
- fmt.Printf("[%v] m => %v\n",workerId,m)
- case <- done:
- fmt.Printf("[%v] is done\n",workerId)
- return
- }
- }
- }
- package main
- import "fmt"
- func main() {
- ch := make(chan string)
- go func() {
- for m := range ch {
- fmt.Println("processed:",m)
- }
- }()
- ch <- "cmd.1"
- ch <- "cmd.2" //won't be processed
- }
- package main
- import (
- "fmt"
- "time"
- )
- func main() {
- ch := make(chan int)
- for i := 0; i <3; i++ {
- go func(idx int) {
- ch <- (idx + 1) * 2
- }(i)
- }
- //get the first result
- fmt.Println(<-ch)
- close(ch) //not ok (you still have other senders)
- //do other work
- time.Sleep(2 * time.Second)
- }
- package main
- import (
- "fmt"
- "time"
- )
- func main() {
- ch := make(chan int)
- done := make(chan struct{})
- for i := 0; i < 3; i++ {
- go func(idx int) {
- select {
- case ch <- (idx + 1) * 2: fmt.Println(idx,"sent result")
- case <- done: fmt.Println(idx,"exiting")
- }
- }(i)
- }
- //get first result
- fmt.Println("result:",<-ch)
- close(done)
- //do other work
- time.Sleep(3 * time.Second)
- }
- package main
- import (
- "fmt"
- "time"
- )
- func main() {
- var ch chan int
- for i := 0; i < 3; i++ {
- go func(idx int) {
- ch <- (idx + 1) * 2
- }(i)
- }
- //get first result
- fmt.Println("result:",<-ch)
- //do other work
- time.Sleep(2 * time.Second)
- }
- package main
- import "fmt"
- import "time"
- func main() {
- inch := make(chan int)
- outch := make(chan int)
- go func() {
- var in <- chan int = inch
- var out chan <- int
- var val int
- for {
- select {
- case out <- val:
- out = nil
- in = inch
- case val = <- in:
- out = outch
- in = nil
- }
- }
- }()
- go func() {
- for r := range outch {
- fmt.Println("result:",r)
- }
- }()
- time.Sleep(0)
- inch <- 1
- inch <- 2
- time.Sleep(3 * time.Second)
- }
- package main
- import "fmt"
- type data struct {
- num int
- key *string
- items map[string]bool
- }
- func (this *data) pmethod() {
- this.num = 7
- }
- func (this data) vmethod() {
- this.num = 8
- *this.key = "v.key"
- this.items["vmethod"] = true
- }
- func main() {
- key := "key.1"
- d := data{1,&key,make(map[string]bool)}
- fmt.Printf("num=%v key=%v items=%v\n",d.num,*d.key,d.items)
- //prints num=1 key=key.1 items=map[]
- d.pmethod()
- fmt.Printf("num=%v key=%v items=%v\n",d.num,*d.key,d.items)
- //prints num=7 key=key.1 items=map[]
- d.vmethod()
- fmt.Printf("num=%v key=%v items=%v\n",d.num,*d.key,d.items)
- //prints num=7 key=v.key items=map[vmethod:true]
- }
- package main
- import (
- "fmt"
- "net/http"
- "io/ioutil"
- )
- func main() {
- resp, err := http.Get("https://api.ipify.org?format=json")
- defer resp.Body.Close()//not ok
- if err != nil {
- fmt.Println(err)
- return
- }
- body, err := ioutil.ReadAll(resp.Body)
- if err != nil {
- fmt.Println(err)
- return
- }
- fmt.Println(string(body))
- }
- package main
- import (
- "fmt"
- "net/http"
- "io/ioutil"
- )
- func main() {
- resp, err := http.Get("https://api.ipify.org?format=json")
- if err != nil {
- fmt.Println(err)
- return
- }
- defer resp.Body.Close()//ok, most of the time :-)
- body, err := ioutil.ReadAll(resp.Body)
- if err != nil {
- fmt.Println(err)
- return
- }
- fmt.Println(string(body))
- }
- package main
- import (
- "fmt"
- "net/http"
- "io/ioutil"
- )
- func main() {
- resp, err := http.Get("https://api.ipify.org?format=json")
- if resp != nil {
- defer resp.Body.Close()
- }
- if err != nil {
- fmt.Println(err)
- return
- }
- body, err := ioutil.ReadAll(resp.Body)
- if err != nil {
- fmt.Println(err)
- return
- }
- fmt.Println(string(body))
- }
- package main
- import (
- "fmt"
- "net/http"
- "io/ioutil"
- )
- func main() {
- req, err := http.NewRequest("GET","http://golang.org",nil)
- if err != nil {
- fmt.Println(err)
- return
- }
- req.Close = true
- //or do this:
- //req.Header.Add("Connection", "close")
- resp, err := http.DefaultClient.Do(req)
- if resp != nil {
- defer resp.Body.Close()
- }
- if err != nil {
- fmt.Println(err)
- return
- }
- body, err := ioutil.ReadAll(resp.Body)
- if err != nil {
- fmt.Println(err)
- return
- }
- fmt.Println(len(string(body)))
- }
- package main
- import (
- "fmt"
- "net/http"
- "io/ioutil"
- )
- func main() {
- tr := &http.Transport{DisableKeepAlives: true}
- client := &http.Client{Transport: tr}
- resp, err := client.Get("http://golang.org")
- if resp != nil {
- defer resp.Body.Close()
- }
- if err != nil {
- fmt.Println(err)
- return
- }
- fmt.Println(resp.StatusCode)
- body, err := ioutil.ReadAll(resp.Body)
- if err != nil {
- fmt.Println(err)
- return
- }
- fmt.Println(len(string(body)))
- }
- package main
- import "fmt"
- type data struct {
- num int
- fp float32
- complex complex64
- str string
- char rune
- yes bool
- events <-chan string
- handler interface{}
- ref *byte
- raw [10]byte
- }
- func main() {
- v1 := data{}
- v2 := data{}
- fmt.Println("v1 == v2:",v1 == v2) //prints: v1 == v2: true
- }
- package main
- import "fmt"
- type data struct {
- num int //ok
- checks [10]func() bool //not comparable
- doit func() bool //not comparable
- m map[string] string //not comparable
- bytes []byte //not comparable
- }
- func main() {
- v1 := data{}
- v2 := data{}
- fmt.Println("v1 == v2:",v1 == v2)
- }
- package main
- import (
- "fmt"
- "reflect"
- )
- type data struct {
- num int //ok
- checks [10]func() bool //not comparable
- doit func() bool //not comparable
- m map[string] string //not comparable
- bytes []byte //not comparable
- }
- func main() {
- v1 := data{}
- v2 := data{}
- fmt.Println("v1 == v2:",reflect.DeepEqual(v1,v2)) //prints: v1 == v2: true
- m1 := map[string]string{"one": "a","two": "b"}
- m2 := map[string]string{"two": "b", "one": "a"}
- fmt.Println("m1 == m2:",reflect.DeepEqual(m1, m2)) //prints: m1 == m2: true
- s1 := []int{1, 2, 3}
- s2 := []int{1, 2, 3}
- fmt.Println("s1 == s2:",reflect.DeepEqual(s1, s2)) //prints: s1 == s2: true
- }
- package main
- import (
- "fmt"
- "reflect"
- )
- func main() {
- var b1 []byte = nil
- b2 := []byte{}
- fmt.Println("b1 == b2:",reflect.DeepEqual(b1, b2)) //prints: b1 == b2: false
- }
- package main
- import (
- "fmt"
- "bytes"
- )
- func main() {
- var b1 []byte = nil
- b2 := []byte{}
- fmt.Println("b1 == b2:",bytes.Equal(b1, b2)) //prints: b1 == b2: true
- }
- package main
- import (
- "fmt"
- "reflect"
- "encoding/json"
- )
- func main() {
- var str string = "one"
- var in interface{} = "one"
- fmt.Println("str == in:",str == in,reflect.DeepEqual(str, in))
- //prints: str == in: true true
- v1 := []string{"one","two"}
- v2 := []interface{}{"one","two"}
- fmt.Println("v1 == v2:",reflect.DeepEqual(v1, v2))
- //prints: v1 == v2: false (not ok)
- data := map[string]interface{}{
- "code": 200,
- "value": []string{"one","two"},
- }
- encoded, _ := json.Marshal(data)
- var decoded map[string]interface{}
- json.Unmarshal(encoded, &decoded)
- fmt.Println("data == decoded:",reflect.DeepEqual(data, decoded))
- //prints: data == decoded: false (not ok)
- }
- subtle.ConstantTimeCompare()
- ).
- Incorrect:
- package main
- import "fmt"
- func main() {
- recover() //doesn't do anything
- panic("not good")
- recover() //won't be executed :)
- fmt.Println("ok")
- }
- Works:
- package main
- import "fmt"
- func main() {
- defer func() {
- fmt.Println("recovered:",recover())
- }()
- panic("not good")
- }
- Fails:
- package main
- import "fmt"
- func doRecover() {
- fmt.Println("recovered =>",recover()) //prints: recovered => <nil>
- }
- func main() {
- defer func() {
- doRecover() //panic is not recovered
- }()
- panic("not good")
- }
- package main
- import "fmt"
- func main() {
- data := []int{1,2,3}
- for _,v := range data {
- v *= 10 //original item is not changed
- }
- fmt.Println("data:",data) //prints data: [1 2 3]
- }
- package main
- import "fmt"
- func main() {
- data := []int{1,2,3}
- for i,_ := range data {
- data[i] *= 10
- }
- fmt.Println("data:",data) //prints data: [10 20 30]
- }
- package main
- import "fmt"
- func main() {
- data := []*struct{num int} { {1},{2},{3} }
- for _,v := range data {
- v.num *= 10
- }
- fmt.Println(data[0],data[1],data[2]) //prints &{10} &{20} &{30}
- }
- package main
- import "fmt"
- func get() []byte {
- raw := make([]byte,10000)
- fmt.Println(len(raw),cap(raw),&raw[0]) //prints: 10000 10000 <byte_addr_x>
- return raw[:3]
- }
- func main() {
- data := get()
- fmt.Println(len(data),cap(data),&data[0]) //prints: 3 10000 <byte_addr_x>
- }
- package main
- import "fmt"
- func get() []byte {
- raw := make([]byte,10000)
- fmt.Println(len(raw),cap(raw),&raw[0]) //prints: 10000 10000 <byte_addr_x>
- res := make([]byte,3)
- copy(res,raw[:3])
- return res
- }
- func main() {
- data := get()
- fmt.Println(len(data),cap(data),&data[0]) //prints: 3 3 <byte_addr_y>
- }
- package main
- import (
- "fmt"
- "bytes"
- )
- func main() {
- path := []byte("AAAA/BBBBBBBBB")
- sepIndex := bytes.IndexByte(path,'/')
- dir1 := path[:sepIndex]
- dir2 := path[sepIndex+1:]
- fmt.Println("dir1 =>",string(dir1)) //prints: dir1 => AAAA
- fmt.Println("dir2 =>",string(dir2)) //prints: dir2 => BBBBBBBBB
- dir1 = append(dir1,"suffix"...)
- path = bytes.Join([][]byte{dir1,dir2},[]byte{'/'})
- fmt.Println("dir1 =>",string(dir1)) //prints: dir1 => AAAAsuffix
- fmt.Println("dir2 =>",string(dir2)) //prints: dir2 => uffixBBBB (not ok)
- fmt.Println("new path =>",string(path))
- }
- package main
- import (
- "fmt"
- "bytes"
- )
- func main() {
- path := []byte("AAAA/BBBBBBBBB")
- sepIndex := bytes.IndexByte(path,'/')
- dir1 := path[:sepIndex:sepIndex] //full slice expression
- dir2 := path[sepIndex+1:]
- fmt.Println("dir1 =>",string(dir1)) //prints: dir1 => AAAA
- fmt.Println("dir2 =>",string(dir2)) //prints: dir2 => BBBBBBBBB
- dir1 = append(dir1,"suffix"...)
- path = bytes.Join([][]byte{dir1,dir2},[]byte{'/'})
- fmt.Println("dir1 =>",string(dir1)) //prints: dir1 => AAAAsuffix
- fmt.Println("dir2 =>",string(dir2)) //prints: dir2 => BBBBBBBBB (ok now)
- fmt.Println("new path =>",string(path))
- }
- import "fmt"
- func main() {
- s1 := []int{1,2,3}
- fmt.Println(len(s1),cap(s1),s1) //prints 3 3 [1 2 3]
- s2 := s1[1:]
- fmt.Println(len(s2),cap(s2),s2) //prints 2 2 [2 3]
- for i := range s2 { s2[i] += 20 }
- //still referencing the same array
- fmt.Println(s1) //prints [1 22 23]
- fmt.Println(s2) //prints [22 23]
- s2 = append(s2,4)
- for i := range s2 { s2[i] += 10 }
- //s1 is now "stale"
- fmt.Println(s1) //prints [1 22 23]
- fmt.Println(s2) //prints [32 33 14]
- }
- Fails:
- package main
- import "sync"
- type myMutex sync.Mutex
- func main() {
- var mtx myMutex
- mtx.Lock() //error
- mtx.Unlock() //error
- }
- Compile Errors:
- /tmp/sandbox106401185/main.go:9: mtx.Lock undefined (type myMutex has no field or method Lock) /tmp/sandbox106401185/main.go:10: mtx.Unlock undefined (type myMutex has no field or method Unlock)
- Works:
- package main
- import "sync"
- type myLocker struct {
- sync.Mutex
- }
- func main() {
- var lock myLocker
- lock.Lock() //ok
- lock.Unlock() //ok
- }
- Works:
- package main
- import "sync"
- type myLocker sync.Locker
- func main() {
- var lock myLocker = new(sync.Mutex)
- lock.Lock() //ok
- lock.Unlock() //ok
- }
- package main
- import "fmt"
- func main() {
- loop:
- for {
- switch {
- case true:
- fmt.Println("breaking out...")
- break loop
- }
- }
- fmt.Println("out!")
- }
- Incorrect:
- package main
- import (
- "fmt"
- "time"
- )
- func main() {
- data := []string{"one","two","three"}
- for _,v := range data {
- go func() {
- fmt.Println(v)
- }()
- }
- time.Sleep(3 * time.Second)
- //goroutines print: three, three, three
- }
- Works:
- package main
- import (
- "fmt"
- "time"
- )
- func main() {
- data := []string{"one","two","three"}
- for _,v := range data {
- vcopy := v //
- go func() {
- fmt.Println(vcopy)
- }()
- }
- time.Sleep(3 * time.Second)
- //goroutines print: one, two, three
- }
- Works:
- package main
- import (
- "fmt"
- "time"
- )
- func main() {
- data := []string{"one","two","three"}
- for _,v := range data {
- go func(in string) {
- fmt.Println(in)
- }(v)
- }
- time.Sleep(3 * time.Second)
- //goroutines print: one, two, three
- }
- Incorrect:
- package main
- import (
- "fmt"
- "time"
- )
- type field struct {
- name string
- }
- func (p *field) print() {
- fmt.Println(p.name)
- }
- func main() {
- data := []field{ {"one"},{"two"},{"three"} }
- for _,v := range data {
- go v.print()
- }
- time.Sleep(3 * time.Second)
- //goroutines print: three, three, three
- }
- Works:
- package main
- import (
- "fmt"
- "time"
- )
- type field struct {
- name string
- }
- func (p *field) print() {
- fmt.Println(p.name)
- }
- func main() {
- data := []field{ {"one"},{"two"},{"three"} }
- for _,v := range data {
- v := v
- go v.print()
- }
- time.Sleep(3 * time.Second)
- //goroutines print: one, two, three
- }
- package main
- import (
- "fmt"
- "time"
- )
- type field struct {
- name string
- }
- func (p *field) print() {
- fmt.Println(p.name)
- }
- func main() {
- data := []*field{ {"one"},{"two"},{"three"} }
- for _,v := range data {
- go v.print()
- }
- time.Sleep(3 * time.Second)
- }
- package main
- import "fmt"
- func main() {
- var i int = 1
- defer fmt.Println("result =>",func() int { return i * 2 }())
- i++
- //prints: result => 2 (not ok if you expected 4)
- }
- package main
- import (
- "fmt"
- "os"
- "path/filepath"
- )
- func main() {
- if len(os.Args) != 2 {
- os.Exit(-1)
- }
- start, err := os.Stat(os.Args[1])
- if err != nil || !start.IsDir(){
- os.Exit(-1)
- }
- var targets []string
- filepath.Walk(os.Args[1], func(fpath string, fi os.FileInfo, err error) error {
- if err != nil {
- return err
- }
- if !fi.Mode().IsRegular() {
- return nil
- }
- targets = append(targets,fpath)
- return nil
- })
- for _,target := range targets {
- f, err := os.Open(target)
- if err != nil {
- fmt.Println("bad target:",target,"error:",err) //prints error: too many open files
- break
- }
- defer f.Close() //will not be closed at the end of this code block
- //do something with the file...
- }
- }
- package main
- import (
- "fmt"
- "os"
- "path/filepath"
- )
- func main() {
- if len(os.Args) != 2 {
- os.Exit(-1)
- }
- start, err := os.Stat(os.Args[1])
- if err != nil || !start.IsDir(){
- os.Exit(-1)
- }
- var targets []string
- filepath.Walk(os.Args[1], func(fpath string, fi os.FileInfo, err error) error {
- if err != nil {
- return err
- }
- if !fi.Mode().IsRegular() {
- return nil
- }
- targets = append(targets,fpath)
- return nil
- })
- for _,target := range targets {
- func() {
- f, err := os.Open(target)
- if err != nil {
- fmt.Println("bad target:",target,"error:",err)
- return
- }
- defer f.Close() //ok
- //do something with the file...
- }()
- }
- }
- Incorrect:
- package main
- import "fmt"
- func main() {
- var data interface{} = "great"
- if data, ok := data.(int); ok {
- fmt.Println("[is an int] value =>",data)
- } else {
- fmt.Println("[not an int] value =>",data)
- //prints: [not an int] value => 0 (not "great")
- }
- }
- Works:
- package main
- import "fmt"
- func main() {
- var data interface{} = "great"
- if res, ok := data.(int); ok {
- fmt.Println("[is an int] value =>",res)
- } else {
- fmt.Println("[not an int] value =>",data)
- //prints: [not an int] value => great (as expected)
- }
- }
- func First(query string, replicas ...Search) Result {
- c := make(chan Result)
- searchReplica := func(i int) { c <- replicas[i](query) }
- for i := range replicas {
- go searchReplica(i)
- }
- return <-c
- }
- func First(query string, replicas ...Search) Result {
- c := make(chan Result,len(replicas))
- searchReplica := func(i int) { c <- replicas[i](query) }
- for i := range replicas {
- go searchReplica(i)
- }
- return <-c
- }
- func First(query string, replicas ...Search) Result {
- c := make(chan Result,1)
- searchReplica := func(i int) {
- select {
- case c <- replicas[i](query):
- default:
- }
- }
- for i := range replicas {
- go searchReplica(i)
- }
- return <-c
- }
- func First(query string, replicas ...Search) Result {
- c := make(chan Result)
- done := make(chan struct{})
- defer close(done)
- searchReplica := func(i int) {
- select {
- case c <- replicas[i](query):
- case <- done:
- }
- }
- for i := range replicas {
- go searchReplica(i)
- }
- return <-c
- }
- package main
- import "fmt"
- type data struct {
- name string
- }
- func (p *data) print() {
- fmt.Println("name:",p.name)
- }
- type printer interface {
- print()
- }
- func main() {
- d1 := data{"one"}
- d1.print() //ok
- var in printer = data{"two"} //error
- in.print()
- m := map[string]data {"x":data{"three"}}
- m["x"].print() //error
- }
- Compile Errors:
- /tmp/sandbox017696142/main.go:21: cannot use data literal (type data) as type printer in assignment: data does not implement printer (print method has pointer receiver)
- /tmp/sandbox017696142/main.go:25: cannot call pointer method on m["x"]
- /tmp/sandbox017696142/main.go:25: cannot take the address of m["x"]
- Fails:
- package main
- type data struct {
- name string
- }
- func main() {
- m := map[string]data {"x":{"one"}}
- m["x"].name = "two" //error
- }
- Compile Error:
- /tmp/sandbox380452744/main.go:9: cannot assign to m["x"].name
- package main
- import "fmt"
- type data struct {
- name string
- }
- func main() {
- s := []data one
- s[0].name = "two" //ok
- fmt.Println(s) //prints: [{two}]
- }
- package main
- import "fmt"
- type data struct {
- name string
- }
- func main() {
- m := map[string]data {"x":{"one"}}
- r := m["x"]
- r.name = "two"
- m["x"] = r
- fmt.Printf("%v",m) //prints: map[x:{two}]
- }
- package main
- import "fmt"
- type data struct {
- name string
- }
- func main() {
- m := map[string]*data {"x":{"one"}}
- m["x"].name = "two" //ok
- fmt.Println(m["x"]) //prints: &{two}
- }
- package main
- type data struct {
- name string
- }
- func main() {
- m := map[string]*data {"x":{"one"}}
- m["z"].name = "what?" //???
- }
- package main
- import "fmt"
- func main() {
- var data *byte
- var in interface{}
- fmt.Println(data,data == nil) //prints: <nil> true
- fmt.Println(in,in == nil) //prints: <nil> true
- in = data
- fmt.Println(in,in == nil) //prints: <nil> false
- //'data' is 'nil', but 'in' is not 'nil'
- }
- Incorrect:
- package main
- import "fmt"
- func main() {
- doit := func(arg int) interface{} {
- var result *struct{} = nil
- if(arg> 0) {
- result = &struct{}{}
- }
- return result
- }
- if res := doit(-1); res != nil {
- fmt.Println("good result:",res) //prints: good result: <nil>
- //'res' is not 'nil', but its value is 'nil'
- }
- }
- Works:
- package main
- import "fmt"
- func main() {
- doit := func(arg int) interface{} {
- var result *struct{} = nil
- if(arg> 0) {
- result = &struct{}{}
- } else {
- ret
- package main
- import (
- "fmt"
- "runtime"
- )
- func main() {
- fmt.Println(runtime.GOMAXPROCS(-1)) //prints: 1
- fmt.Println(runtime.NumCPU()) //prints: 1 (on play.golang.org)
- runtime.GOMAXPROCS(20)
- fmt.Println(runtime.GOMAXPROCS(-1)) //prints: 20
- runtime.GOMAXPROCS(300)
- fmt.Println(runtime.GOMAXPROCS(-1)) //prints: 256
- }
- package main
- import (
- "runtime"
- "time"
- )
- var _ = runtime.GOMAXPROCS(3)
- var a, b int
- func u1() {
- a = 1
- b = 2
- }
- func u2() {
- a = 3
- b = 4
- }
- func p() {
- println(a)
- println(b)
- }
- func main() {
- go u1()
- go u2()
- go p()
- time.Sleep(1 * time.Second)
- }
- 1
- 2
- 3
- 4
- 0
- 2
- 0
- 0
- 1
- 4
- package main
- import "fmt"
- func main() {
- done := false
- go func(){
- done = true
- }()
- for !done {
- }
- fmt.Println("done!")
- }
- package main
- import "fmt"
- func main() {
- done := false
- go func(){
- done = true
- }()
- for !done {
- fmt.Println("not done!") //not inlined
- }
- fmt.Println("done!")
- }
- go build -gcflags -m
- ).
- package main
- import (
- "fmt"
- "runtime"
- )
- func main() {
- done := false
- go func(){
- done = true
- }()
- for !done {
- runtime.Gosched()
- }
- fmt.Println("done!")
- }
来源: https://juejin.im/entry/5b3c3802e51d45199940b946