go语言中的for循环

go语言中的for循环

假如给你一个字符串让你遍历获取其中的内容,或者查找其中的是否包含某个字符串,你会如何做?

理所当然的我们选择了for循环来进行遍历

在go语言中使用比较多的两个循环一个是for i,一个是for range,这两者都能够很有效的对一个集合体进行遍历。(string也是一个集合体),下面我们来具体展示一下他们之间的区别

for i
func main() {
	str := "Hello, 世界"
	for i := 0; i < len(str); i++ {
		ch := str[i]
		fmt.Println(i, ch, , string(ch))
	}
}

这是一段很简单的代码,首先思考一下他的答案是什么?

0 72 H
1 101 e
2 108 l
3 108 l
4 111 o
5 44 ,
6 32  
7 228 ä
8 184 ¸
9 150 
10 231 ç
11 149 
12 140 

这是它的答案,为什么会产生这么一个结果?

首先需要了解一下字符串在go语言的具体实现,简单的来说字符串是一系列8位字节的集合,一般以UTF-8的编码格式,看一下go的源码中src/runtime/string.go,string的定义如下

type stringStruct struct {
    str unsafe.Pointer
    len int
}

string由两部分组成一个是指针,一个是长度,指针指向一个数组的首地址,长度为当前后面的len长度的数组为一个整体:

func gostringnocopy(str *byte) string {
	ss := stringStruct{str: unsafe.Pointer(str), len: findnull(str)}
	s := *(*string)(unsafe.Pointer(&ss))
	return s
}

从上面这段代码可以看到,string的表现形式是[]byte,string就是byte数组,并且他是一个struct

好了,现在就能够理解为什么for i的结构是这样了

for range

再尝试一下for range遍历吧!

func main() {
	str := "Hello, 世界"
	for i, ch := range str {
		fmt.Println(i, ch, string(ch))
	}
}

既然专门提出来了,那么肯定不一样了,直接看结果

0 72 H
1 101 e
2 108 l
3 108 l
4 111 o
5 44 ,
6 32  
7 1999010 30028

为什么会产生这样的结果,那么先看一下range的伪代码吧

len_temp := len(range)
range_temp := range
for index_temp = 0; index_temp < len_temp; index_temp++ {
    value_temp = range_temp[index_temp]
    index = index_temp
    value = value_temp
    original body
  }

它是一个语法塘,底层其实是一个for i的循环,在字符串中迭代 unicode 编码。第一个返回值是rune的起始字节位置index,然后第二个是 rune 自己。(byte与rune自行了解)

虽然range是建立在for i之上的,但是它有着for i很多不具备的功能,比如遍历map,channel通道的遍历,至于为什么它这么这个牛逼,内部方法写得好是一方面,map,channel的数据结构也决定了for i的无法遍历,以后再详细介绍。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值