GO 語言的 for…range
能做什麼呢?
for…range
如何使用 ?
for…range
的返回值有哪些情況,可以對於任何資料結構使用嗎?
for…range
的返回值如果不需要,可以如何處理?
for…range
的資料是如何傳遞的?
剛學習 golang 的 xdm 會不會有上面的疑問?其實很簡單,我們就一個一個的來分享和實操一遍
GO 語言的 for…range
能做什麼呢?
golang 的 for…range
是 go 自身的語法,可以用來遍歷資料結構,有如下資料結構可以遍歷
- 切片 slice
- 陣列 array
- map 雜湊表
- channel 通道
for…range
如何使用 ?
我們分別來看看可以如何使用他們,for…range
相當於一個迭代器,可以遍歷資料結構的鍵/索引 和值
陣列 array
- 初始化一個陣列
- 使用
for…range
遍歷 , 對應的是 索引 和 值
func main() {
myArray := [5]int{1, 2, 3, 4, 5}
for i, v := range myArray {
fmt.Printf("%d -- %d -- %p\n", i, v, &v)
}
}
切片 slice
- 初始化一個切片
- 使用
for…range
遍歷 , 對應的是 索引 和 值
mySlice := []int{1, 2, 3, 4, 5}
for i, v := range mySlice {
fmt.Printf("%d -- %d -- %p\n", i, v, &v)
}
map 雜湊表
- 初始化一個 map 雜湊表
- 使用
for…range
遍歷 , map 對應的 鍵值對
myMap := map[string]string{
"name": "xmt",
"hobby": "program",
"addr": "mengli",
}
for k, v := range myMap {
fmt.Printf("%s -- %s -- %p\n", k, v, &v)
}
channel 通道
- 建立一個可以緩衝 10 個 int 型別資料的通道
- 建立一個協程專門向通道中寫入資料
- 主協程遍歷通道,讀取資料
package main
import "fmt"
var myCh = make(chan int, 10)
func writeCh() {
for i := 0; i < 5; i++ {
myCh <- i
}
close(myCh)
}
func main() {
go writeCh()
for {
for data := range myCh {
fmt.Println(data)
}
break
}
}
for…range
的返回值有哪些情況,可以對於任何資料結構使用嗎?
並不是所有資料結構都可以使用 for…range
的,如下結構可以使用這個方法
返回值 1 | 返回值 2 | 資料傳遞 | |
---|---|---|---|
字串 | 索引 | 索引對應的值 | 值傳遞 |
陣列或者切片 | 索引 | 索引對應的值 | 陣列:值傳遞 切片:引用傳遞 |
雜湊表 | 鍵 | 鍵對應的值 | 指標 |
通道 | 通道中的資料 | 指標 |
for…range
的返回值如果不需要,可以如何處理?
相信寫過 golang 的 xdm 都知道,go 裡面對於我們不需要的返回值,都可以使用 -
來表示 ,因此 for…range
當然也可以這樣
例如:
myMap := map[string]string{
"name": "xmt",
"hobby": "program",
"addr": "mengli",
}
for _, v := range myMap {
fmt.Printf("%s -- %p\n", v, &v)
}
for…range
的資料是如何傳遞的?
資料都是透過複製傳遞的,也就是都是值傳遞的,只不過由於資料結構不一樣,陣列和切片在這裡還是有一些區別的
前面的文章,我們有說到,切片,對應著 有 3 個元素的資料結構,一個是 cap,一個是 len, 一個是 ptr ,指向的是一個底層陣列
切片是引用傳遞,但是傳遞資料的時候,切片這個變數是值傳遞,但是它實際指向的底層陣列還是不會變的
我們們來寫一個 demo 檢視一下:
我們思路是這個樣子:
遍歷一個 陣列/切片,在遍歷當前值的時候,去修改後面索引對應的值,全部遍歷完畢後,檢視結果中,實際的資料是否會被修改掉,若修改掉了,則是切片是傳引用,若沒有修改掉,則是陣列是傳值
陣列的效果
myArray := [5]int{1, 2, 3, 4, 5}
fmt.Println(myArray)
for i, v := range myArray {
if i == 0{
myArray[2] = 888
}
fmt.Printf("%d -- %d -- %p\n", i, v, &myArray[i])
}
效果如下:
go run main.go
[1 2 3 4 5]
0 -- 1 -- 0x1189c120
1 -- 2 -- 0x1189c124
2 -- 3 -- 0x1189c128
3 -- 4 -- 0x1189c12c
4 -- 5 -- 0x1189c130
切片的效果
mySlice := []int{1, 2, 3, 4, 5}
fmt.Println(mySlice)
for i, v := range mySlice {
if i == 0{
mySlice[2] = 888
}
fmt.Printf("%d -- %d -- %p\n", i, v, &mySlice[i])
}
效果如下:
go run main.go
[1 2 3 4 5]
0 -- 1 -- 0x1140e340
1 -- 2 -- 0x1140e344
2 -- 888 -- 0x1140e348
3 -- 4 -- 0x1140e34c
4 -- 5 -- 0x1140e350
透過上述的案例,相信心裡都有點譜了吧
歡迎點贊,關注,收藏
朋友們,你的支援和鼓勵,是我堅持分享,提高質量的動力
好了,本次就到這裡
技術是開放的,我們的心態,更應是開放的。擁抱變化,向陽而生,努力向前行。
我是阿兵雲原生,歡迎點贊關注收藏,下次見~