分享
  1. 首页
  2. 文章

Go语言 你可能不知道的十个技巧

abv123456789 · · 13312 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

1、匿名结构体

全局组合

var config struct {// 定义一个用于全局配置结构体
 APIKey string
 OAuthConfig oauth.Config
}
config.APIKey = "BADC0C0A"

数据模板

data := struct {//匿名结构体的定义
 Title string
 Users []*User
}{//同时初始化
 title,
 users,
}
err := tmpl.Execute(w, data)

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

测试表(用作测试数据构造)

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},
}

嵌套加锁

var hits struct {
 sync.Mutex
 n int
}
hits.Lock()
hits.n++//十对"n"的操作是安全的
hits.Unlock()

2、嵌套结构体

反序列化深层嵌套的json

{"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的文档注释

% godoc sync Mutex

输出

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 命令

% godoc -src sync Mutex

输出

// 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、获取指定域名下的包

go get camlistore.org/pkg/netutil go help remote 可查看更详细的信息.

6、模拟一个文件系统

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

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、方法表达式

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

os/exec中的实际例子:

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发送和接收消息

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发送广播

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
 }
}

另外一个例子

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

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)
}

有疑问加站长微信联系(非本文作者)

本文来自:CSDN博客

感谢作者:abv123456789

查看原文:Go语言 你可能不知道的十个技巧

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
13312 次点击 ∙ 4 赞
1 回复 | 直到 2018年03月27日 12:05:03
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏