资源管理 defer
defer
- 在defer语句位置处就计算用到的参数值,只是放在在函数返回值之前执行
- 一个函数中的多个defer是栈的结构,先进后出,位置靠前的defer后执行
func f1() {
defer fmt.Println(1)
defer fmt.Println(2)
fmt.Println(3)
//即使defer后面有return,panic,也会执行defer
panic("发生错误")
fmt.Println(4)
}
func f2() {
i := 1
//这个defer语句要输出的值在此处就已确认 1,并不是在函数结束、执行defer时才确认
defer fmt.Println(i)
i = 10
}
defer常用于确保在函数结束时执行语句,常见的使用场景如下
- Open/Close 资源、连接的关闭
- Lock/Unlock 锁的释放
- PrintHeader/PrintFooter
func write(filePath string, str string) {
//创建文件,可以使用相对路径、绝对路径,但文件名之前的路径要是已存在的,不然会报错
file, err := os.Create(filePath)
if err != nil {
panic(err)
}
//函数结束时关闭文件
defer file.Close()
//使用缓冲写入文件
writer := bufio.NewWriter(file)
//函数结束时把缓冲区的内容刷出到文件
defer writer.Flush()
for i := 0; i < 10; i++ {
writer.WriteString(str)
}
}
func main() {
write("test/1.txt", "xxx\n")
}
错误处理
panic和recover
panic要慎用,不能随便用
//格式化输出,%c是字符
//fmt.Printf("%d%s%d=%d\n", a, operator, b, a*b)
//panic
//panic(fmt.Sprintf("不支持的运算符:%s", operator))
//支持字符串
//panic("不支持的运算符:" + operator)
//整型int转字符串
// panic("不合法的分数值:" + strconv.Itoa(score))
panic("发生错误")
//panic(errors.New("xxx错误"))
待整理
io
func main() {
//文件读写
const filePath = "C:/Users/chy/Desktop/1.txt"
if content, err := ioutil.ReadFile(filePath);err!=nil {
fmt.Println(err)
}else {
//返回的content是byte[],转换为string输出
fmt.Printf("%s\n", content)
}
}
http
func Get(url string) string {
resp, err := http.Get(url)
if err != nil {
panic(err)
}
result, err := httputil.DumpResponse(
resp, true)
resp.Body.Close()
if err != nil {
panic(err)
}
return string(result)
}
web
func main() {
const dir = "/list/"
http.HandleFunc(dir,
func(writer http.ResponseWriter, request *http.Request) {
path := request.URL.Path[len(dir):]
file, err := os.Open("E:\\go_path\\src\\go_demo\\http-server\\"+path)
if err != nil {
panic(err.Error())
}
defer file.Close()
all, err := ioutil.ReadAll(file)
if err != nil {
panic(err)
}
writer.Write(all)
})
err := http.ListenAndServe(":8888", nil)
if err != nil {
panic(err)
}
}