defer应该在if后面,如果文件为空,close会崩溃。
package main
import (
"os"
"fmt"
)
func main() {
file, err := os.Open("/null")
defer func() {
err := file.Close()
if err != nil {
fmt.Println("close error: ", err)
} else {
fmt.Println("close no error")
}
}()
if err != nil {
fmt.Println("open error! ", err)
return
}
}
数组是值类型,也是按值传递的;切片slide是引用类型。
import后面跟的是包的路径,而不是包名;
同一个目录下可以有多个.go文件,但是只能有一个包;
使用第三方库时,先将源码编译成.a文件放到临时目录下,然后去链接这个.a文件,而不是go install安装的那个.a文件;
使用标准库时,直接链接.a文件,即使修改了源码,也不会从新编译源码;
不管使用的是标准库还是第三方库,源码都是必须存在的,即使使用的是.a文件。
当内置的panic()函数调用时,外围函数或方法的执行会立即终止。然后,任何延迟执行(defer)的函数或方法都会被调用,就像其外围函数正常返回一样。最后,调用返回到该外围函数的调用者,就像该外围调用函数或方法调用了panic()一样,因此该过程一直在调用栈中重复发生:函数停止执行,调用延迟执行函数等。当到达main()函数时不再有可以返回的调用者,因此这个过程会终止,并将包含传入原始panic()函数中的值的调用栈信息输出到os.Stderr。
panic需要等defer结束后才会向上传递。出现panic的时候,会先按照defer的后入先出的顺序执行,最后才会执行panic。
几乎所有类型包括内置类型,均可以自定义方法。除了指针。func (a *Integer) Multi(b Integer){ }。
无缓冲的channel是同步的,而有缓冲的channel是非同步的。比如
c1:=make(chan int) //无缓冲
c2:=make(chan int,1) //有缓冲
c1<-1
无缓冲的,不仅仅是 向 c1 通道放 1 而是 一直要有别的协程 <-c1 接手了 这个参数,那么c1<-1才会继续下去,要不然就一直阻塞着,
而 c2<-1 则不会阻塞,因为缓冲大小是1, 只有当放第二个值的时候 第一个还没被人拿走,这时候才会阻塞。
打个比喻:
无缓冲的——就是一个送信人去你家门口送信 ,你不在家他不走,你一定要接下信,他才会走。因此无缓冲保证信能到你手上。
有缓冲的 就是一个送信人去你家仍到你家的信箱转身就走 ,除非你的信箱满了他必须等信箱空下来。有缓冲的保证信能进你家的邮箱。
go中实现try catch finally的机智是defer,panic,recover机制。对已经关闭的channel发送数据会导致panic异常
package main
import (
"fmt"
)
func main() {
var ch chan int = nil //make(chan int)
go func() {
for i := 1; i < 10; i++ {
ch <- 5
}
close(ch)
}()
for i := 0; i < 15; i++ {
fmt.Println(<-ch)
}
}
GoStub框架的使用场景很多,依次为: