golang——關於for循環的學習


1、for循環的用法

(1)常規用法

func main() {
	slice := []int{1, 2, 3, 4, 5, 6}
	//方式1
	for i := 0; i < len(slice); i++ {
		if i < 10 {
			slice = append(slice, 0)
		}
		fmt.Printf("%v ", slice[i]) //1 2 3 4 5 6 0 0 0 0 0 0 0 0 0 0
	}
	fmt.Println()
	//方式2
	slice = slice[:6]
	n := len(slice)
	for i := 0; i < n; i++ {
		fmt.Printf("%v ", slice[i]) //1 2 3 4 5 6
	}
	fmt.Println()
}

方式1每次循環都會執行len函數,適用於動態循環(循環出口是動態的);

方式2適用於固定循環(一般為固定循環次數),固定循環不推薦使用方式1(如果循環出口是一個耗時的操作,會影響效率); 

(2)死循環

func main() {
	slice := []int{1, 2, 3, 4, 5, 6}
	for {
		slice = append(slice, 0)
		if len(slice) > 10 {
			break
		}
	}
	fmt.Println(slice) //[1 2 3 4 5 6 0 0 0 0 0]
}

死循環一般用於監聽操作,或者循環出口不唯一,需配合break結束循環。

(3)for...range

func main() {
	slice := []int{1, 2, 3, 4, 5, 6}
	for i := range slice {
		fmt.Printf("%d ", i) //0 1 2 3 4 5
	}
	fmt.Println()
	for i, v := range slice {
		fmt.Printf("slice[%d]=%d ", i, v)
		//slice[0]=1 slice[1]=2 slice[2]=3 slice[3]=4 slice[4]=5 slice[5]=6
	}
}

for...range支持迭代 數組、切片、字符串、map、只讀channel或可讀可寫channel;

for...range迭代類型不同返回值不同,數組、切片、字符串返回下標和值,map返回鍵和值,channel返回值;  

2、for與for range在遍歷字符串時的差別

func main() {
	str := "abcd篤志弘毅"
	n := len(str)
	for i := 0; i < n; i++ {
		fmt.Printf("%c", str[i]) //abcd笃志弘æ¯
	}
	fmt.Println()
	for i, v := range str {
		fmt.Printf("str[%d]=%c", i, v)
		//str[0]=astr[1]=bstr[2]=cstr[3]=dstr[4]=篤str[7]=志str[10]=弘str[13]=毅
	}
}

for遍歷字符串時是按字節(byte)進行遍歷,超出一個字節的編碼字符會出現亂碼;

for...range遍歷字符串時是按字符(rune)進行遍歷;  

3、for...range注意點

(1)迭代切片時相當於遍歷切片副本,原始切片的append或再切片不影響整個迭代

func main() {
	slice := []int{1, 2, 3, 4, 5, 6}
	for i, v := range slice {
		//迭代切片相當於temp:=slice[:],遍歷temp切片
		//slice的append或再切片slice[1:2]不影響整個迭代
		slice = append(slice, 0)
		slice = slice[0:len(slice)]
		fmt.Printf("slice[%d]=%d ", i, v)
		//slice[0]=1 slice[1]=2 slice[2]=3 slice[3]=4 slice[4]=5 slice[5]=6
	}
	fmt.Println("\n", slice) // [1 2 3 4 5 6 0 0 0 0 0 0]
}

(2)值類型的迭代修改不影響原始數據,指針類型的迭代修改會影響原始數據

func main() {
	//切片
	slice := []int{1, 2, 3, 4, 5, 6}
	for _, v := range slice {
		v += v
	}
	fmt.Println(slice) //[1 2 3 4 5 6]
	//map
	m := map[int]*int{}
	m[1] = new(int)
	m[2] = new(int)
	*m[1] = 1
	*m[2] = 2
	fmt.Println(*m[1], *m[2]) //1 2
	for _, v := range m {
		*v++
	}
	fmt.Println(*m[1], *m[2]) //2 3
}

(3)for...range迭代map時

》訪問是隨機的,遍歷結果可能不一樣;

func main() {
	m := map[int]int{0: 0, 1: 1, 2: 2, 3: 3, 4: 4}
	for k, v := range m {
		fmt.Printf("%v %v,", k, v) //2 2,3 3,4 4,0 0,1 1,
	}
}

》可以正常進行刪除操作,因為迭代使用的是拷貝;

func main() {
	m := map[int]*int{}
	m[1] = new(int)
	m[2] = new(int)
	*m[1] = 1
	*m[2] = 2
	fmt.Println(*m[1], *m[2]) //1 2
	for k, v := range m {
		delete(m, k)
		*v++
		fmt.Printf("%v ", *v) //2 3
	}
}

》可以正常進行添加操作,由於map底層是哈希表,哈希表的元素不具備順序性,所以新添加的元素可能不會出現在后續的迭代中;

func main() {
	m := map[int]string{1: "一", 2: "二"}
	for k, v := range m {
		m[k+2] = "測試"
		fmt.Println(k, v)
	}
	fmt.Println(m)
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM