zoukankan      html  css  js  c++  java
  • 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("
    ", 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)
    }
    
    笃志:“博学而笃志,切问而近思,仁在其中矣。”
    弘毅:“士不可以不弘毅,任重而道远。”
    止于至善:“大学之道,在明明德,在亲民,在止于至善。”
    关注:笃志弘毅,止于至善
  • 相关阅读:
    Hadoop(二)—— HDFS
    Hive(一)—— 启动与基本使用
    Flume(一) —— 启动与基本使用
    Kafka(四) —— KafkaProducer源码阅读
    Flink(一) —— 启动与基本使用
    Kafka(三) —— 集群监控
    Hadoop(一)—— 启动与基本使用
    Spark(二)—— 标签计算、用户画像应用
    二. python数组和列表
    一. python数据结构与算法
  • 原文地址:https://www.cnblogs.com/dzhy/p/10977779.html
Copyright © 2011-2022 走看看