Go 언어에서 defer
키워드를 사용하면 함수가 끝날 때까지 코드 실행을 지연할 수 있습니다. 개발 중에는 열린 파일 설명자 닫기, 연결 닫기, 리소스 해제 등의 후속 작업을 완료하기 위해 defer
키워드를 사용하는 경우가 많습니다. defer
关键字可以将代码延迟到函数结束之前执行。在开发中,我们经常使用defer
关键字完成善后工作,如关闭打开的文件描述符、关闭连接以及释放资源等。
func demo0() { fileName := "./test.txt" f, _ := os.OpenFile(fileName, os.O_RDONLY, 0) defer f.Close() contents, _ := ioutil.ReadAll(f) fmt.Println(string(contents))}
defer
关键字一般紧跟在打开资源代码的后面,防止后续忘记释放资源,defer 声明的代码实际上要等到函数结束之前才会被执行。defer 虽然简单易用,但如果忽略了它的特性,就会在开发中面临困惑。于是,我总结了 defer 的五大特性,通过 8 个demo逐步介绍 defer 的特性。
特性1:多个 defer 时的调用顺序:先进后出
使用多个 defer 关键字时,先被声明的 defer 语句后被调用。类似于“栈”先进后出的特性,defer 的这一特性也很好理解,先被打开的资源,可能会被后续代码依赖,所以要后释放才安全。
func demo1() { for i := 0; i <h2 id="特性-作用域为当前函数-不同函数下拥有不同的-defer-栈">特性2:作用域为当前函数,不同函数下拥有不同的 defer 栈</h2><p>运行 demo2 ,从结果中可以看出,第一个匿名函数和第二个匿名函数的 defer 执行顺序没有关系。<br>defer 作用域仅为当前函数,在当前函数最后执行,所以不同函数下拥有不同的 defer 栈。</p><pre class="brush:php;toolbar:false">func demo2() { func() { defer fmt.Println(1) defer fmt.Println(2) }() fmt.Println("=== 新生代农民工啊 ===") func() { defer fmt.Println("a") defer fmt.Println("b") }()}// 2// 1// === 新生代农民工啊 ===// b// a
特性3:defer 后的函数形参在声明时确认(预计算参数)
运行 demo3_1 ,根据结果,我们可以得出:defer 在声明时,就已经确认了形参n的值,而不是在执行时确认的;所以,后续变量 num 无论如何改变都不影响 defer 的输出结果。
func demo3_1() { num := 0 defer func(n int) { fmt.Println("defer:", n) }(num) // 等同 defer fmt.Println("defer:", num) for i := 0; i <p>运行 demo3_2,为什么这里 defer 的最终输出的结果会和变量 num 相同?因为这里使用的是指针。<br>defer <strong>声明时</strong>,已经确认了形参p指针的指向地址,指向变量 num;后续变量 num 发生改变。所以在 defer <strong>执行时</strong>,输出的是p指针指向的变量num的当前值。</p><pre class="brush:php;toolbar:false">func demo3_2() { num := 0 p := &num defer func(p *int) { fmt.Println("defer:", *p) }(p) for i := 0; i <p>再看一下 demo3_3,defer 打印的变量并没有通过函数参数传入,在defer<strong>执行时</strong>,才获取的”全局变量”num,所以 defer 输出结果与变量num一致。</p><pre class="brush:php;toolbar:false">func demo3_3() { num := 0 defer func() { fmt.Println("defer:", num) }() for i := 0; i <h2 id="特性-return-与-defer-执行顺序-return-先-defer-后">特性4:return 与 defer 执行顺序:return 先 defer 后</h2><p>运行 demo4_1,可以发现 defer、return 都是在函数最后执行,但 return 先于 defer 执行;</p><pre class="brush:php;toolbar:false">func demo4_1() (int, error) { defer fmt.Println("defer") return fmt.Println("return")}// return// defer
这一点从输出结果上显而易见,但当 return、defer 的执行顺序和**函数返回值**
“相遇”时,又将会产生许多复杂的场景。
在 demo4_2 中,函数使用命名返回值
,最终输出结果为7。其中经历了这几个过程:
(首先)变量 num 作为返回值,初始值为0;
(其次)随后变量 num 被赋值为 10;
(然后)return 时,变量 num 作为返回值被重新赋值为 2;
(接着)defer 在 return 后执行,拿到变量 num 进行修改,值为7;
-
(最后)变量 num 作为返回值,最终函数返回结果为7;
func demo4_2() (num int) { num = 10 defer func() { num += 5 }() return 2}// 7
再来看一个例子。
在 demo4_3 中,函数使用匿名返回值
func demo4_3() int { num := 10 defer func() { num += 5 }() return 2}// 2
defer
키워드는 일반적으로 나중에 리소스 해제를 잊어버리는 것을 방지하기 위해 리소스를 여는 코드를 따릅니다. defer는 간단하고 사용하기 쉽지만 해당 기능을 무시하면 개발 중에 혼란을 겪게 됩니다. 그래서 defer의 5가지 주요 기능을 요약하고, 8개의 데모를 통해 defer의 기능을 점진적으로 소개했습니다. - 특징 1: 다중 defer 사용 시 호출 순서: 선입, 최후 여러 defer 키워드를 사용하는 경우 먼저 선언된 defer 문이 나중에 호출됩니다. "스택" 선입, 최후 기능과 마찬가지로 이 지연 기능도 이해하기 쉽습니다. 먼저 열리는 리소스는 후속 코드에 의존할 수 있으므로 나중에 출시해도 안전합니다.
- 기능 2: 범위는 현재 함수이며, 함수마다 다른 연기 스택이 있습니다Demo2를 실행하면 첫 번째 익명 함수와 두 번째 익명 함수의 실행을 연기하는 순서를 알 수 있습니다. 관계가 없습니다.
defer의 범위는 현재 함수뿐이며 현재 함수의 끝에서 실행되므로 함수마다 서로 다른 defer 스택이 있습니다. - 특징 3: 연기 후 함수 매개변수는 선언 시 확인됩니다(사전 계산된 매개변수) demo3_1을 실행하면 결과에 따라 가져올 수 있음: defer 형식 매개변수 n의 값은 실행이 아닌 선언 시에 확인되었으므로 이후에 변수 num을 변경해도 영향을 받지 않습니다. 연기 출력. rrreee
- demo3_2를 실행하세요. 여기서 defer의 최종 출력 결과가 왜 변수 num과 같나요? 여기서 포인터가 사용되기 때문입니다.
defer 선언되면 형식 매개변수 p 포인터가 가리키는 주소가 확인되어 변수 num을 가리키며 이후에 변수 num이 변경됩니다. 따라서 defer가 실행되면 출력은 p 포인터가 가리키는 변수 num의 현재 값입니다.rrreee
defer3_3을 다시 보세요. defer가 출력한 변수는 함수 매개변수를 통해 전달되지 않습니다. "전역 변수" num은 defer가실행될 때만 얻어지므로 defer의 출력 결과는 일관됩니다. 변수 num을 사용합니다. rrreee - 기능 4: return 및 defer 실행 순서: return 먼저 defer한 다음 demo4_1을 실행하면 defer 및 return이 함수 끝에서 실행되지만 return이 defer보다 먼저 실행되는 것을 볼 수 있습니다.
rrreee
이것은; 출력 결과에서 알 수 있듯이 그러나 반환 및 연기의 실행 순서와**함수 반환 값**
"만남"이 발생하면 많은 복잡한 시나리오가 발생합니다.
demo4_2에서 함수는명명된 반환 값
을 사용하며 최종 출력 결과는 7입니다. 다음 프로세스를 거쳤습니다. (첫 번째) num 변수가 반환 값으로 사용되며 초기 값은 0입니다.
(then) return 시 변수 num을 반환 값으로 2에 재할당합니다.
func demo5_1() { defer fmt.Println(1) defer fmt.Println(2) defer fmt.Println(3) panic("没点赞异常") // 触发defer出栈执行 defer fmt.Println(4) // 得不到执行}
func demo5_2() { defer func() { if err := recover(); err != nil { fmt.Println(err, "问题不大") } }() panic("没点赞异常") // 触发defer出栈执行 // ...}
demo4_3에서 함수는
익명 반환 값
을 사용하며 최종 결과 출력은 2입니다. 프로세스는 다음과 같습니다. 🎜🎜🎜🎜가 함수에 들어가면 반환 값 변수는 이때 생성되지 않습니다. 🎜🎜🎜🎜는 변수 num을 생성하고 🎜🎜🎜🎜가 반환될 때 값 10을 할당합니다. 함수 반환 값 변수가 생성되고 값이 2로 할당됩니다. 이 반환 값 변수를 익명 변수 또는 변수 a, b, c, d...로 간주할 수 있지만 🎜🎜인 경우 변수 num이 아닙니다. 🎜🎜defer, 변수 num을 어떻게 수정하더라도 함수 반환 값과는 아무런 관련이 없습니다. 🎜🎜🎜🎜따라서 최종 함수 반환 결과는 2입니다. 🎜rrreee🎜Feature 5: 패닉이 발생하면 선언됩니다. defer는 스택에서 튀어나와 실행됩니다. 🎜🎜demo5_1을 실행하면 패닉이 발생하면 선언된 defer가 스택에서 튀어나온 후 패닉이 발생하고 패닉 이후에 선언된 defer는 실행되지 않는 것을 볼 수 있습니다. 🎜rrreee🎜 이 기능을 사용하면 복구를 연기하여 패닉을 포착하여 프로그램 충돌을 방지할 수 있습니다. 🎜rrreee🎜첨부🎜🎜전체 코드: 🎜github.com/newbugcoder/learngo/tre...🎜🎜🎜🎜위 내용은 8개의 데모를 사용하여 Go 언어 연기의 5가지 주요 기능을 이해하세요의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

Golang은 높은 동시성 작업에 더 적합하지만 Python은 유연성에 더 많은 장점이 있습니다. 1. Golang은 Goroutine 및 채널을 통해 동시성을 효율적으로 처리합니다. 2. Python은 GIL의 영향을받는 스레딩 및 Asyncio에 의존하지만 여러 동시성 방법을 제공합니다. 선택은 특정 요구 사항을 기반으로해야합니다.

Golang과 C의 성능 차이는 주로 메모리 관리, 컴파일 최적화 및 런타임 효율에 반영됩니다. 1) Golang의 쓰레기 수집 메커니즘은 편리하지만 성능에 영향을 줄 수 있습니다. 2) C의 수동 메모리 관리 및 컴파일러 최적화는 재귀 컴퓨팅에서 더 효율적입니다.

선택 GOLANGFORHIGHERFERFERFORMANDCONDCURRENCY, TILDFORBECTERVICES 및 NNETWORKPRAMPHING; SELECTPYTHONFORRAPIDDEVENTURMENT, DATASCIENCE 및 MACHINEARNINGDUETOITSTINTIVENDEXTENDIVERIRIES.

Golang과 Python은 각각 고유 한 장점이 있습니다. Golang은 고성능 및 동시 프로그래밍에 적합하지만 Python은 데이터 과학 및 웹 개발에 적합합니다. Golang은 동시성 모델과 효율적인 성능으로 유명하며 Python은 간결한 구문 및 풍부한 라이브러리 생태계로 유명합니다.

Golang과 Python은 어떤 측면에서 사용하기 쉽고 부드러운 학습 곡선을 가지고 있습니까? Golang은 높은 동시성과 고성능 요구에 더 적합하며, 학습 곡선은 C 언어 배경을 가진 개발자에게는 비교적 온화합니다. Python은 데이터 과학 및 빠른 프로토 타이핑에 더 적합하며 학습 곡선은 초보자에게 매우 매끄 럽습니다.

Golang과 C는 각각 공연 경쟁에서 고유 한 장점을 가지고 있습니다. 1) Golang은 높은 동시성과 빠른 발전에 적합하며 2) C는 더 높은 성능과 세밀한 제어를 제공합니다. 선택은 프로젝트 요구 사항 및 팀 기술 스택을 기반으로해야합니다.

Golang은 빠른 개발 및 동시 프로그래밍에 적합한 반면 C는 극심한 성능과 기본 제어가 필요한 프로젝트에 더 적합합니다. 1) Golang의 동시성 모델은 Goroutine 및 Channel을 통한 동시성 프로그래밍을 단순화합니다. 2) C의 템플릿 프로그래밍은 일반적인 코드 및 성능 최적화를 제공합니다. 3) Golang의 쓰레기 수집은 편리하지만 성능에 영향을 줄 수 있습니다. C의 메모리 관리는 복잡하지만 제어는 괜찮습니다.

goimpactsdevelopmentpositively throughlyspeed, 효율성 및 단순성.


핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

SecList
SecLists는 최고의 보안 테스터의 동반자입니다. 보안 평가 시 자주 사용되는 다양한 유형의 목록을 한 곳에 모아 놓은 것입니다. SecLists는 보안 테스터에게 필요할 수 있는 모든 목록을 편리하게 제공하여 보안 테스트를 더욱 효율적이고 생산적으로 만드는 데 도움이 됩니다. 목록 유형에는 사용자 이름, 비밀번호, URL, 퍼징 페이로드, 민감한 데이터 패턴, 웹 셸 등이 포함됩니다. 테스터는 이 저장소를 새로운 테스트 시스템으로 간단히 가져올 수 있으며 필요한 모든 유형의 목록에 액세스할 수 있습니다.

WebStorm Mac 버전
유용한 JavaScript 개발 도구

mPDF
mPDF는 UTF-8로 인코딩된 HTML에서 PDF 파일을 생성할 수 있는 PHP 라이브러리입니다. 원저자인 Ian Back은 자신의 웹 사이트에서 "즉시" PDF 파일을 출력하고 다양한 언어를 처리하기 위해 mPDF를 작성했습니다. HTML2FPDF와 같은 원본 스크립트보다 유니코드 글꼴을 사용할 때 속도가 느리고 더 큰 파일을 생성하지만 CSS 스타일 등을 지원하고 많은 개선 사항이 있습니다. RTL(아랍어, 히브리어), CJK(중국어, 일본어, 한국어)를 포함한 거의 모든 언어를 지원합니다. 중첩된 블록 수준 요소(예: P, DIV)를 지원합니다.

VSCode Windows 64비트 다운로드
Microsoft에서 출시한 강력한 무료 IDE 편집기

DVWA
DVWA(Damn Vulnerable Web App)는 매우 취약한 PHP/MySQL 웹 애플리케이션입니다. 주요 목표는 보안 전문가가 법적 환경에서 자신의 기술과 도구를 테스트하고, 웹 개발자가 웹 응용 프로그램 보안 프로세스를 더 잘 이해할 수 있도록 돕고, 교사/학생이 교실 환경 웹 응용 프로그램에서 가르치고 배울 수 있도록 돕는 것입니다. 보안. DVWA의 목표는 다양한 난이도의 간단하고 간단한 인터페이스를 통해 가장 일반적인 웹 취약점 중 일부를 연습하는 것입니다. 이 소프트웨어는
