Go语言范围Range的具体使用

 更新时间:2024年01月09日 09:38:58   作者:242030  
range关键字在for循环中用于遍历数组,切片,通道或映射的项目,本文主要介绍了Go语言范围Range的具体使用,具有一定的参考价值,感兴趣的可以了解一下

Go 语言中 range 关键字用于 for 循环中迭代数组(array)、切片(slice)、通道(channel)或集合(map)的元素。在数组和切片中它返回元素的索引和索引对应的值,在集合中返回 key-value 对。

for 循环的 range 格式可以对 slice、map、数组、字符串等进行迭代循环。

// 格式如下
// 代码中的key和value是可以省略的
for key, value := range oldMap {
    newMap[key] = value
}
// 如果只想读取key,格式如下
for key := range oldMap
// 或者
for key, _ := range oldMap
// 如果只想读取value,格式如下
for _, value := range oldMap
// 遍历简单的数组,2**%d的结果为索引对应的次方数
package main

import "fmt"

var pow = []int{1, 2, 4, 8, 16, 32, 64, 128}

func main() {
	/*
		2**0 = 1
		2**1 = 2
		2**2 = 4
		2**3 = 8
		2**4 = 16
		2**5 = 32
		2**6 = 64
		2**7 = 128
	*/
	for i, v := range pow {
		fmt.Printf("2**%d = %d\n", i, v)
	}
}

# 程序输出
2**0 = 1
2**1 = 2
2**2 = 4
2**3 = 8
2**4 = 16
2**5 = 32
2**6 = 64
2**7 = 128 

// for循环的range格式可以省略key和value
package main

import "fmt"

func main() {
	map1 := make(map[int]float32)
	map1[1] = 1.0
	map1[2] = 2.0
	map1[3] = 3.0
	map1[4] = 4.0
	/*
		key is: 1 - value is: 1.000000
		key is: 2 - value is: 2.000000
		key is: 3 - value is: 3.000000
		key is: 4 - value is: 4.000000
	*/
	// 读取 key 和 value
	for key, value := range map1 {
		fmt.Printf("key is: %d - value is: %f\n", key, value)
	}
	/*
		key is: 1
		key is: 2
		key is: 3
		key is: 4
	*/
	// 读取 key
	for key := range map1 {
		fmt.Printf("key is: %d\n", key)
	}
	/*
		value is: 1.000000
		value is: 2.000000
		value is: 3.000000
		value is: 4.000000
	*/
	// 读取 value
	for _, value := range map1 {
		fmt.Printf("value is: %f\n", value)
	}
}
// range遍历其他数据结构
package main

import "fmt"

func main() {
	//这是我们使用 range 去求一个 slice 的和。使用数组跟这个很类似
	nums := []int{2, 3, 4}
	sum := 0
	for _, num := range nums {
		sum += num
	}
	// sum: 9
	fmt.Println("sum:", sum)
	//在数组上使用 range 将传入索引和值两个变量。上面那个例子我们不需要使用该元素的序号,所以我们使用空白符"_"省略了。有时侯我们确实需要知道它的索引。
	for i, num := range nums {
		if num == 3 {
			// index: 1
			fmt.Println("index:", i)
		}
	}
	//range 也可以用在 map 的键值对上。
	kvs := map[string]string{"a": "apple", "b": "banana"}
	/*
		a -> apple
		b -> banana
	*/
	for k, v := range kvs {
		fmt.Printf("%s -> %s\n", k, v)
	}

	/*
		0 103
		1 111
	*/
	//range也可以用来枚举 Unicode 字符串。第一个参数是字符的索引,第二个是字符(Unicode的值)本身。
	for i, c := range "go" {
		fmt.Println(i, c)
	}
}
// Range 简单循环
package main

import "fmt"

func main() {
	nums := []int{1, 2, 3, 4}
	length := 0
	for range nums {
		length++
	}
	// 4
	fmt.Println(length)
}
// 通过 range 获取参数列表
package main

import (
	"fmt"
	"os"
)

func main() {
	// 1
	fmt.Println(len(os.Args))
	for _, arg := range os.Args {
		// C:\Users\zhangshixing\AppData\Local\Temp\___go_build_hello_go.exe
		fmt.Println(arg)
	}
}
// Go 中的中文采用UTF-8编码,因此逐个遍历字符时必须采用for-each形式
package main

import "fmt"

func main() {
	// str: hello
	// 0x68 h, 0x65 e, 0x6c l, 0x6c l, 0x6f o,
	// 0x68, 0x65, 0x6c, 0x6c, 0x6f,
	printStr("hello")
	fmt.Println()
	fmt.Println()
	// str: 中国人
	// 0x4e2d 中, 0x56fd 国, 0x4eba 人,
	// 0xe4, 0xb8, 0xad, 0xe5, 0x9b, 0xbd, 0xe4, 0xba, 0xba,
	printStr("中国人")
}

func printStr(s string) {
	fmt.Println("str: " + s)
	for _, v := range s {
		fmt.Printf("0x%x %c, ", v, v)
	}
	fmt.Println()
	for i := 0; i < len(s); i++ {
		fmt.Printf("0x%x, ", s[i])
	}
}

涉及指针时需要注意,v 是个单独的地址:

package main

import "fmt"

func main() {
	nums := [3]int{5, 6, 7}
	/*
		源值地址: 0xc00000c108          value的地址: 0xc000016098
		源值地址: 0xc00000c110          value的地址: 0xc000016098
		源值地址: 0xc00000c118          value的地址: 0xc000016098
	*/
	for k, v := range nums {
		fmt.Println("源值地址:", &nums[k], " \t value的地址:", &v)
	}
}

range复用临时变量:

package main

import "sync"

func main() {
	wg := sync.WaitGroup{}
	si := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
	for i := range si {
		wg.Add(1)
		go func() {
			print(i)
			wg.Done()
		}()
	}
	wg.Wait()
}

# 程序输出
9999999999

导致这样结果的原因是:

(1)、for range 下的迭代变量i的值是共用的。

(2)、main函数所在的 goroutine 和后续启动的 goroutines 存在竞争关系。

package main

import "sync"

func main() {
	wg := sync.WaitGroup{}
	si := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
	for i := range si {
		wg.Add(1)
		// 这里有一个实参到形参的值拷贝
		go func(a int) {
			print(a)
			wg.Done()
		}(i)
	}
	wg.Wait()
}

# 程序输出
9865207314

到此这篇关于Go语言范围Range的具体使用的文章就介绍到这了,更多相关Go语言范围Range内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家! 

相关文章

  • Go Slice扩容的这些坑你踩过哪些

    Go Slice扩容的这些坑你踩过哪些

    这篇文章主要为大家详细介绍了Golang中对切片Slice的append操作时会遇到的踩坑经验分享,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一下
    2023-03-03
  • Goland激活码破解永久版及安装详细教程(亲测可以)

    Goland激活码破解永久版及安装详细教程(亲测可以)

    这篇文章主要介绍了Goland激活码破解永久版及安装详细教程(亲测可以),本文通过实例图文相结合给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-10-10
  • 深入探究Go语言的错误策略与异常机制

    深入探究Go语言的错误策略与异常机制

    本文深入探讨了Go语言的错误策略与异常机制,主要介绍了错误处理的重要性,以及Go语言中的错误类型和处理函数,此外还讨论了Go语言的异常机制,包括panic和recover函数的使用,需要的朋友可以参考下
    2024-02-02
  • MacOS中 VSCode 安装 GO 插件失败问题的快速解决方法

    MacOS中 VSCode 安装 GO 插件失败问题的快速解决方法

    这篇文章主要介绍了MacOS中 VSCode 安装 GO 插件失败问题的快速解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-05-05
  • Go语言结构体定义和使用方法

    Go语言结构体定义和使用方法

    这篇文章主要介绍了Go语言结构体定义和使用方法,以实例形式分析了Go语言中结构体的定义和使用技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-02-02
  • Golang实现异步上传文件支持进度条查询的方法

    Golang实现异步上传文件支持进度条查询的方法

    这篇文章主要介绍了Golang实现异步上传文件支持进度条查询的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-10-10
  • Go中groutine通信与context控制实例详解

    Go中groutine通信与context控制实例详解

    随着context包的引入,标准库中很多接口因此加上了context参数,下面这篇文章主要给大家介绍了关于Go中groutine通信与context控制的相关资料,需要的朋友可以参考下
    2022-02-02
  • Golang中函数(Function)和方法(Method)的区别详解

    Golang中函数(Function)和方法(Method)的区别详解

    在Golang中,大家必然会频繁使用到函数(Function)和方法(Method),但是有的同学可能并没有注意过函数和方法的异同点,函数和方法都是用来执行特定任务的代码块,虽然很相似,但也有很大的区别,所以本文将详细讲解函数和方法的定义以及它们的异同点
    2023-07-07
  • Golang接口使用教程详解

    Golang接口使用教程详解

    在 Go 语言中接口包含两种含义:它既是方法的集合, 同时还是一种类型并且在Go 语言中是隐式实现的。本文通过示例详细介绍了Golang接口的使用,需要的可以参考一下
    2022-09-09
  • Golang单元测试与覆盖率的实例讲解

    Golang单元测试与覆盖率的实例讲解

    这篇文章主要介绍了Golang单元测试与覆盖率的实例讲解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-11-11

最新评论