Golang -- 10件你不知道的事情
本文翻译 从 文章进行翻译,在此表示感谢 10 things you (probably) don’t know about golang匿名结构体 (Anonymous structs)Template data (模板数据)data := struct {
Title string
Users []*User //猜测 User 是一个接口,接口指针的切片
} {
title,USERS,}
err := tmpl.Execute(w,data)
(Cheaper and safer than using map[string]interface{}) 嵌入式锁 (Embedded Lock)var hits struct{
sync.Mutex //匿名对象的方法,(类似于一种继承的方式)
n int
}
hits.Lock() // (和C++中的继承很类似)
hits.n++
hits.Unlock()
Nested structs 嵌套的结构Decoding deeply nested JSON data{"data" : {"children" : [ {"data" : { "title" : "The Go homepage","url" : "http://golang.org/"}},... ]}}
type Item struct{
Titel string
URL string
}
type Response struct{ //使用 Structs 来表示 Json 数据,十分巧妙
Data struct {
Children []struct {
Data Item
}
}
}
记得在 golang的 json 库中,既可以直接使用这样的结构来进行 JSON 数据的解析和发送。
Command-line godoc 命令行 godoc% godoc sync Mutex //这里 godoc 是命令,sync是包名,Mutex是类型名
显示值如下
godc -src 可以直接显示golang的源代码% godoc -src sync Mutex 显示如下:
可以看到,显示了 unexported state! 便于我们对源代码进行深入的探索. Mock out the file system (模仿文件系统)现在有一个 package,这个包需要和 file system 进行协作,但是你不想让你的测试使用真正的磁盘,应该怎么办? var fs fileSystem = osFS{}
type fileSystem interface { //应该是标准库中文件系统的接口
Open(name string) (file,error)
Stat(name string) (os.fileInfo,error)
}
type file interface { //标准库 中 file的接口
io.Closer
io.Reader
io.ReaderAt
io.Seeker
Stat() (os.FileInfo,error)
}
type osFs struct{} // osFs 类型,实现了 fileSystem 接口。
func (osFs) Open(name string) (file,error) //只要它的返回值,实现file接口即可
func (osFs) Stat(name string) (os.FileInfo,error)
Method expression (方法表达式)type T struct{} //定义了一个新的类型 T
func (T) Foo(string) {fmt.Println(s)} //定义了这个类型T的一个方法
//fn 是一个函数类型的变量,将这个方法赋值给这个变量
// 值得注意的是: fn 的类型是 func(T,string)
// Foo 函数的类型是: func (T) Foo(string) 类型
var fn func(T,sring) = T.Foo
os/exec 中的一个真实的例子: func (c *Cmd) stdin() (f *os.File,error)
func (c *Cmd) stdout() (f *os.File,error)
func (c *Cmd) stderr() (f *os.File,error)
type F func(*cmd) (*os.File,error)
for _,setupFd := range []F{(*Cmd).stdin,(*Cmd).stdout,(*Cmd).stderr} { //定义了一个切片
fd,err := steupFd(c)
if err != nil {
c.closeDescriptors(c.closeAfterStart)
c.closeDescriptors(c.closeAfterWait)
return err
}
c.childFiles = append(c.childFiles,fd)
}
Send and receive on the same channelpackage main
import "fmt"
var battle = make(chan string) //定义一个 channel 变量
func warrior(name string,done chan struct{}) {
//现在问题来了:同一个select中,同一个 channel的情况应该如何应对?
select {
case oppoent := <-battle: //battle 接受数据
fmt.Printf("%s beat %sn",name,oppoent)
case battle <- name: //battle 发送数据
// I lost
}
done <- struct{}{}
}
func main() {
done := make(chan struct{})
langs := []string{"Go","C","C++","Java","Perl","Python"}
for _,s := range langs {
go warrior(s,done) //生成多个 Goroutine
}
for _ = range langs {
<-done //等待 Goroutine结束,什么时候整个进程结束?
}
}
多次运行程序,输出并不一样:
第二次运行:
现在问题是: 自己的猜测: Using close to broadcast (使用 close 进行广播)package main
import (
"fmt"
"math/rand" //这样子写
"time"
)
func waiter(i int,block,done chan struct{}) {
time.Sleep(time.Duration(rand.Intn(3000)) * time.Millisecond)
fmt.Println(i,"waiting...")
<-block //所有的 goroutine 会阻塞在 block这里,直到 close(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,done)
}
time.Sleep(5 * time.Second)
close(block) //关闭的时候,所有阻塞的 block 将会停止阻塞 (相当于进行了一次广播)
for i := 0; i < 4; i++ {
<-done
}
}
程序输出如下: 3 waiting... 2 waiting... 1 waiting... 0 waiting... 3 done! 2 done! 1 done! 0 done!
NIl channel in selectfunc worker(i int,ch chan work,quit chan struct{}) {
for {
select {
case w :=<- ch:
if quit == nil { //一个 channel == nil ?
w.Refuse();
fmt.Println("worker",i,"refused",w)
break;
}
w.Do();
case <-quit:
fmt.Println("worker","quiting")
quit = nil (赋值成 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)
}
上述代码有些不太懂得地方。 总结总体来说,比较难的地方,在于 channel 和 struct。 1. channel 的各种利用,来实现同步 和异步,并发等功能。只能在代码中进行探索了。 2. 有关 golang 的内存模型这些东西,不是很理解,很多地方不明不白的。只能等到以后慢慢理解了。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |