go语言中的for循环

TonoT · · 1562 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

## go语言中的for循环 *假如给你一个字符串让你遍历获取其中的内容,或者查找其中的是否包含某个字符串,你会如何做?* #### 理所当然的我们选择了for循环来进行遍历 在go语言中使用比较多的两个循环一个是**for i**,一个是**for range**,这两者都能够很有效的对一个集合体进行遍历。(string也是一个集合体),下面我们来具体展示一下他们之间的区别 #### for i ```go func main() { str := "Hello, 世界" for i := 0; i < len(str); i++ { ch := str[i] fmt.Println(i, ch, , string(ch)) } } ``` 这是一段很简单的代码,首先思考一下他的答案是什么? ```json 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的定义如下 ```go type stringStruct struct { str unsafe.Pointer len int } ``` string由两部分组成一个是指针,一个是长度,指针指向一个数组的首地址,长度为当前后面的len长度的数组为一个整体: ```go 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遍历吧! ```go func main() { str := "Hello, 世界" for i, ch := range str { fmt.Println(i, ch, string(ch)) } } ``` 既然专门提出来了,那么肯定不一样了,直接看结果 ```json 0 72 H 1 101 e 2 108 l 3 108 l 4 111 o 5 44 , 6 32 7 19990 世 10 30028 界 ``` 为什么会产生这样的结果,那么先看一下range的伪代码吧 ```go 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的无法遍历,以后再详细介绍。

有疑问加站长微信联系(非本文作者))

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1562 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传