1. 匿名结构体

  • 全局组合
1
2
3
4
5
var config struct {//定义一个用于全局配置结构体  APIKey string  OAuthConfig oauth.Config } config.APIKey = "BADC0C0A" 

  • 数据模板
1
2
3
4
5
6
7
8
data := struct {//匿名结构体的定义  Title string  Users []*User }{//同时初始化  title,  users, } err := tmpl.Execute(w, data) 

(比map[string]interface{}消耗更小和更安全)

  • 测试表(用作测试数据构造)
1
2
3
4
5
6
7
8
9
10
var indexRuneTests = []struct {  s string  rune rune  out int }{  {"a A x", 'A', 2},  {"some_text=some_value", '=', 9},  {"☺a", 'a', 3},  {"a☻☺b", '☺', 4}, } 

  • 嵌套加锁
1
2
3
4
5
6
7
var hits struct {  sync.Mutex  n int } hits.Lock() hits.n++//十对“n”的操作是安全的 hits.Unlock() 

2. 嵌套结构体

  • 反序列化深层嵌套的json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{"data": {"children": [  {"data": {  "title": "The Go homepage",  "url": "http://golang.org/"  }},  ... ]}} type Item struct {  Title string  URL string } type Response struct {  Data struct {  Children []struct {  Data Item  }  } } 

3. godoc命令,输出package的文档注释

1
% godoc sync Mutex 

输出

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  package sync  import "sync"  TYPES  type Mutex struct {  // contains filtered or unexported fields }  A Mutex is a mutual exclusion lock. Mutexes can be created as part of  other structures; the zero value for a Mutex is an unlocked mutex.  func (m *Mutex) Lock()  Lock locks m. If the lock is already in use, the calling goroutine  blocks until the mutex is available.  func (m *Mutex) Unlock()  Unlock unlocks m. It is a run-time error if m is not locked on entry to  Unlock.   A locked Mutex is not associated with a particular goroutine. It is  allowed for one goroutine to lock a Mutex and then arrange for another  goroutine to unlock it. 

4. godoc -src 命令

1
% godoc -src sync Mutex 

输出

1
2
3
4
5
6
7
// A Mutex is a mutual exclusion lock. // Mutexes can be created as part of other structures; // the zero value for a Mutex is an unlocked mutex. type Mutex struct {  state int32  sema uint32 } 

未导出的元素也将显示!

5. 获取指定域名下的包

1
go get camlistore.org/pkg/netutil 

go help remote 可查看更详细的信息.

6. 模拟一个文件系统

获取到的包里,代码访问了文件系统,但是测试时不希望真正访问磁盘

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var fs fileSystem = osFS{}  type fileSystem interface {  Open(name string) (file, error)  Stat(name string) (os.FileInfo, error) }  type file interface {  io.Closer  io.Reader  io.ReaderAt  io.Seeker  Stat() (os.FileInfo, error) }  // osFS 实现接口filesystem,并访问本地磁盘. type osFS struct{}  func (osFS) Open(name string) (file, error) { return os.Open(name) } func (osFS) Stat(name string) (os.FileInfo, error) { return os.Stat(name) } 

7. 方法表达式

1
2
3
4
type T struct {} func (T) Foo(s string) { println(s) }  var fn func(T, string) = T.Foo//将方法赋值给一个方法变量 

os/exec中的实际例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
func (c *Cmd) stdin() (f *os.File, err error) func (c *Cmd) stdout() (f *os.File, err error) func (c *Cmd) stderr() (f *os.File, err error) type F func(*Cmd) (*os.File, error) for _, setupFd := range []F{(*Cmd).stdin, (*Cmd).stdout, (*Cmd).stderr} {  fd, err := setupFd(c)  if err != nil {  c.closeDescriptors(c.closeAfterStart)  c.closeDescriptors(c.closeAfterWait)  return err  }  c.childFiles = append(c.childFiles, fd) } 

8. 使用统一个Channel发送和接收消息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package main  import "fmt"  var battle = make(chan string)  func warrior(name string, done chan struct{}) {  select {  case opponent := <-battle:  fmt.Printf("%s beat %s\n", name, opponent)  case battle <- name:  // I lost :-(  }  done <- struct{}{} }  func main() {  done := make(chan struct{})  langs := []string{"Go", "C", "C++", "Java", "Perl", "Python"}  for _, l := range langs { go warrior(l, done) }  for _ = range langs { <-done } } 

9. 使用channel的close发送广播

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
func waiter(i int, block, done chan struct{}) {  time.Sleep(time.Duration(rand.Intn(3000)) * time.Millisecond)  fmt.Println(i, "waiting...")  <-block  fmt.Println(i, "done!")  done <- struct{}{} }  func main() {  block, done := make(chan struct{}), make(chan struct{})  for i := 0; i < 4; i++ {  go waiter(i, block, done)  }  time.Sleep(5 * time.Second)  close(block)  for i := 0; i < 4; i++ {  <-done  } } 

另外一个例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
func worker(i int, ch chan Work, quit chan struct{}) {  var quitting bool  for {  select {  case w := <-ch:  if quitting {  w.Refuse(); fmt.Println("worker", i, "refused", w)  break  }  w.Do(); fmt.Println("worker", i, "processed", w)  case <-quit:  fmt.Println("worker", i, "quitting")  quitting = true  }  } } func main() {  ch, quit := make(chan Work), make(chan struct{})  go makeWork(ch)  for i := 0; i < 4; i++ { go worker(i, ch, quit) }  time.Sleep(5 * time.Second)  close(quit)  time.Sleep(2 * time.Second) } 

10. select中使用空channel

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
func worker(i int, ch chan Work, quit chan struct{}) {  for {  select {  case w := <-ch:  if quit == nil {  w.Refuse(); fmt.Println("worker", i, "refused", w)  break  }  w.Do(); fmt.Println("worker", i, "processed", w)  case <-quit:  fmt.Println("worker", i, "quitting")  quit = nil  }  } }  func main() {  ch, quit := make(chan Work), make(chan struct{})  go makeWork(ch)  for i := 0; i < 4; i++ { go worker(i, ch, quit) }  time.Sleep(5 * time.Second)  close(quit)  time.Sleep(2 * time.Second) }