튜토리얼 칼럼에서는 GO의 루프를 통해 작은 구덩이를 사용하는 방법을 공유할 예정이니, 필요한 친구들에게 도움이 되길 바랍니다!
Golang의 프로세스 제어에는 for와 range라는 두 가지 유형의 루프 문이 있습니다.
for 문
1. 대입식, 관계식 또는 논리식, 대입식 { }
for i := 0; i
2. 관계식 또는 논리식 수식 { } code>
n := 10for n > 0 { n--}
3.for { }
1.for 赋值表达式; 关系表达式或逻辑表达式; 赋值表达式 { }
for { fmt.Println("hello world") } // 等价于 // for true { // fmt.Println("hello world") // }
2.for 关系表达式或逻辑表达式 { }
str := "abc" for i, char := range str { fmt.Printf("%d => %s\n", i, string(char)) } for i := range str { //只有一个返回值 fmt.Printf("%d\n", i) } nums := []int{1, 2, 3} for i, num := range nums { fmt.Printf("%d => %d\n", i, num) } kvs := map[string]string{"a": "apple", "b": "banana"} for k, v := range kvs { fmt.Printf("%s => %s\n", k, v) } for k := range kvs { //只有一个返回值 fmt.Printf("%s\n", k) } // 输出结果 // 0 => a // 1 => b // 2 => c // 0 // 1 // 2 // 0 => 1 // 1 => 2 // 2 => 3 // a => apple // b => banana // a // b
3.for { }
func main() { var out []*int for i := 0; i < 3; i++ { // i := i out = append(out, &i) } fmt.Println("值:", *out[0], *out[1], *out[2]) fmt.Println("地址:", out[0], out[1], out[2]) } // 输出结果 // 值: 3 3 3 // 地址: 0xc000012090 0xc000012090 0xc000012090
range语句
Golang range类似迭代器操作,可以对 slice、map、数组、字符串等进行迭代循环。在字符串、数组和切片中它返回 (索引, 值) ,在集合中返回 (键, 值),但若当只有一个返回值时,第一个参数是索引或键。
func main() { a1 := []int{1, 2, 3} a2 := make([]*int, len(a1)) for i, v := range a1 { a2[i] = &v } fmt.Println("值:", *a2[0], *a2[1], *a2[2]) fmt.Println("地址:", a2[0], a2[1], a2[2]) } // 输出结果 // 值: 3 3 3 // 地址: 0xc000012090 0xc000012090 0xc000012090
for循环尤其是range语句,在平时开发过程中频繁使用,但很多开发者(本人算一个)经常会在以下场景中踩坑。
场景一,使用循环迭代器的变量
先来看一个明显的错误:
func main() { var out [][]int for _, i := range [][1]int{{1}, {2}, {3}} { out = append(out, i[:]) } fmt.Println("Values:", out)}// 输出结果// [[3] [3] [3]]
分析
out
是一个整型指针数组变量,在for循环中,声明了一个i
变量,每次循环将i
的地址追加到out
切片中,但是每次追加的其实都是i
变量,因此我们追加的是一个相同的地址,而该地址最终的值是3。
正确做法
解开代码中的注释// i := i
,每次循环时都重新创建一个新的i
变量。
再看一个比较隐秘的错误:
func main() { values := []int{1, 2, 3} wg := sync.WaitGroup{} for _, val := range values { wg.Add(1) go func() { fmt.Println(val) wg.Done() }() } wg.Wait()}// 输出结果// 3// 3// 3
分析
大多数人就是在range
这里给变量赋值的时候踩坑,因为比较隐秘,其实情况和上面的一样,range
在遍历值类型时,其中的v
是一个局部变量,只会声明初始化一次,之后每次循环时重新赋值覆盖前面的,所以给a2[i]
赋值的时候其实都是同一个地址&v
,而v
最终的值为a1
最后一个元素的值,也就是3。
正确做法
①a2[i]
赋值时传递原始指针,即a2[i] = &a1[i]
②创建临时变量t := v
;a2[i] = &t
③闭包(与②原理一样),func(v int) { a2[i] = &v }(v)
更为隐秘的还有:
for _, val := range values { wg.Add(1) val := val go func() { fmt.Println(val) wg.Done() }()}
原理也是一样的,不论遍历多少次,i[:]
总是被本次遍历的值所覆盖
场景二,在循环体内使用goroutines
for _, val := range values { wg.Add(1) go func(val int) { fmt.Println(val) wg.Done() }(val)}
分析
对于主协程来讲,循环是很快就跑完的,而这个时候各个协程可能才开始跑,此时val
的值已经遍历到最后一个了,所以各协程都输出了3
。(如果遍历数据庞大,主协程遍历耗时较久的话,goroutine的输出会根据当时候的val
rrreee
for 루프, 특히 range 문은 일상적인 개발 과정에서 자주 사용되지만, 저를 포함한 많은 개발자들은 다음과 같은 시나리오에서 실수를 자주 저지릅니다. 시나리오 1, 루프 반복기의 변수 사용🎜🎜먼저 명백한 오류를 살펴보겠습니다. 🎜rrreee🎜🎜Analytic🎜🎜🎜Golang 범위는 반복자 작업과 유사하며 슬라이스, 맵, 배열, 문자열 등을 반복할 수 있습니다. 문자열, 배열 및 슬라이스에서는 (인덱스, 값)을 반환하고 컬렉션에서는 (키, 값)을 반환하지만 반환 값이 하나만 있는 경우 첫 번째 인수는 인덱스 또는 키입니다.
rrreee
out
은 for에서 정수 포인터 배열 변수입니다. loop 에서는 i
변수가 선언되고 각 루프는 i
의 주소를 out
슬라이스에 추가하지만 매번 추가되는 것은 실제로는 i
변수이므로 동일한 주소를 추가하고 주소의 최종 값은 3입니다. 🎜🎜🎜올바른 접근 방식🎜🎜🎜코드에서 // i := i
주석을 잠금 해제하고 반복될 때마다 새 i
변수를 다시 만듭니다. 🎜🎜좀 더 비밀스러운 실수를 살펴보겠습니다: 🎜rrreee🎜🎜Analytics🎜🎜🎜대부분의 사람들은 여기
범위
의 변수에 값을 할당할 때 실수를 합니다. 사실 상황은 위와 같습니다. range
가 값 유형을 순회할 때 v
는 지역 변수이며 한 번만 선언되고 초기화된 후 다시 할당됩니다. 이전 항목을 덮어쓰기 위해 반복할 때마다 a2[i]
에 값을 할당할 때 실제로는 모두 동일한 주소 &v
를 가지며 최종 값을 갖습니다. v
는 a1
입니다. 마지막 요소의 값은 3입니다. 🎜🎜🎜올바른 접근 방식🎜🎜🎜1a2[i]
할당 시 원래 포인터를 전달합니다. 즉, a2[i] = &a1[i]
②임시 변수
t := v
생성 a2[i] = &t
③ 클로저(2번과 같은 원리),
func(v int) { a2 [i] = &v }(v)
🎜🎜더 비밀스러운 점은: 🎜rrreee🎜원칙은 동일합니다. 몇 번을 탐색하더라도
i[ :]
항상 이 순회 값으로 덮어쓰기🎜🎜🎜🎜시나리오 2, goroutines 사용🎜rrreee🎜🎜analytic🎜🎜🎜메인 코루틴의 경우 루프는 빠르게 실행되며 이때 각 코루틴은 방금 실행을 시작했습니다. 이때 val
의 값은 마지막 값으로 순회되었으므로 각 코루틴은 3
을 출력합니다. (순회 데이터가 크고 메인 코루틴 순회 시간이 오래 걸리는 경우, 고루틴의 출력은 그때의 val
값을 기준으로 하게 되므로 출력 결과가 동일하지 않을 수 있습니다. 매번.) 🎜🎜🎜 해결책🎜🎜🎜①임시 변수를 사용하세요🎜rrreee🎜②클로저를 사용하세요🎜rrreee위 내용은 Go 루프 탐색의 함정을 기록하세요.의 상세 내용입니다. 자세한 내용은 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를 무료로 생성하십시오.

인기 기사

뜨거운 도구

에디트플러스 중국어 크랙 버전
작은 크기, 구문 강조, 코드 프롬프트 기능을 지원하지 않음

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

안전한 시험 브라우저
안전한 시험 브라우저는 온라인 시험을 안전하게 치르기 위한 보안 브라우저 환경입니다. 이 소프트웨어는 모든 컴퓨터를 안전한 워크스테이션으로 바꿔줍니다. 이는 모든 유틸리티에 대한 액세스를 제어하고 학생들이 승인되지 않은 리소스를 사용하는 것을 방지합니다.

SublimeText3 영어 버전
권장 사항: Win 버전, 코드 프롬프트 지원!

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경
