ch5/ch5-08 #147
ch5/ch5-08
#147
Replies: 6 comments 3 replies
-
练习5.18 - 如果解释的不对,请各路大佬指正🥹func fetch(url string) (filename string, n int64, err error) {
resp, err := http.Get(url)
if err != nil {
return "", 0, err
}
defer resp.Body.Close()
local := path.Base(resp.Request.URL.Path)
if local == "/" {
local = "index.html"
}
fmt.Println(local)
f, err := os.Create(local)
if err != nil {
return "", 0, err
}
n, err = io.Copy(f, resp.Body)
// 这里要搞明白 return defer 和 返回值被赋值给调用者 的先后执行顺序
// 这里先说结论 defer的执行顺序在return之后,但是在返回值返回给调用方之前
// 匿名返回值是在return执行时被声明,有名返回值则是在函数声明的同时被声明,
// 因此在defer语句中只能访问有名返回值,而不能直接访问匿名返回值
// return其实应该包含前后两个步骤:
// 第一步是给返回值赋值(若为有名返回值则直接赋值,若为匿名返回值则先声明再赋值);
// 第二步是调用RET返回指令并传入返回值,而RET则会检查defer是否存在,若存在就先逆序插播defer语句,
// 最后RET携带返回值退出函数;
// 回到这里这个例子, err是被显示定义的有名返回值变量, 所以defer可以访问err
// 这个例子中, 执行到defer时如果Close函数发生错误, 那么返回值中的err将会被改变
defer func() {
if closeErr := f.Close(); closeErr != nil && err == nil {
err = closeErr
}
}()
return local, n, err
} |
Beta Was this translation helpful? Give feedback.
2 replies
-
//5.18
func fetch(url string) (filename string, n int64, err error) {
resp, err := http.Get(url)
if err != nil {
return "", 0, err
}
defer resp.Body.Close()
local := path.Base(resp.Request.URL.Path)
if local == "/" {
local = "index.html"
}
f, err := os.Create(local)
if err != nil {
return "", 0, err
}
n, err = io.Copy(f, resp.Body)
if err != nil {
return "", 0, err
}
defer func() {
if closeErr := f.Close(); closeErr != nil {
err = closeErr
}
}()
return local, n, err
} |
Beta Was this translation helpful? Give feedback.
1 reply
-
func main() {
println("1")
func() {
defer println("2")
println("3")
}()
println("4")
} |
Beta Was this translation helpful? Give feedback.
0 replies
-
|
Beta Was this translation helpful? Give feedback.
0 replies
-
5.18func fetch(url string) (filename string, n int64, err error) {
resp, err := http.Get(url)
if err != nil {
return "", 0, err
}
defer resp.Body.Close()
local := path.Base(resp.Request.URL.Path)
if local == "/" {
local = "index.html"
}
f, err := os.Create(local)
if err != nil {
return "", 0, err
}
// Copy的err为nil时,覆盖
defer func() {
if closeErr := f.Close(); err == nil {
err = closeErr
}
}()
n, err = io.Copy(f, resp.Body)
return local, n, err
} |
Beta Was this translation helpful? Give feedback.
0 replies
-
5.18 用defer修饰一个匿名函数,在fetch退出后会执行,并在产生closeErr时覆盖掉返回值中的err func fetch(url string) (filename string, n int64, err error) {
resp, err := http.Get(url)
if err != nil {
return "", 0, err
}
defer resp.Body.Close()
local := path.Base(resp.Request.URL.Path)
if local == "/" {
local = "index.html"
}
f, err := os.Create(local)
if err != nil {
return "", 0, err
}
defer func() {
if closeErr := f.Close(); err == nil {
err = closeErr
}
}()
n, err = io.Copy(f, resp.Body)
return local, n, err
} |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
ch5/ch5-08
中文版
https://golang-china.github.io/gopl-zh/ch5/ch5-08.html
Beta Was this translation helpful? Give feedback.
All reactions