佳木斯湛栽影视文化发展公司

主頁(yè) > 知識(shí)庫(kù) > 淺析Go語(yǔ)言中的Range關(guān)鍵字

淺析Go語(yǔ)言中的Range關(guān)鍵字

熱門標(biāo)簽:百度競(jìng)價(jià)排名 呼叫中心市場(chǎng)需求 AI電銷 地方門戶網(wǎng)站 鐵路電話系統(tǒng) 服務(wù)外包 網(wǎng)站排名優(yōu)化 Linux服務(wù)器

前言

相信用過(guò)Range的朋友們都知道,Go語(yǔ)言中的range關(guān)鍵字使用起來(lái)非常的方便,它允許你遍歷某個(gè)slice或者map,并通過(guò)兩個(gè)參數(shù)(indexvalue),分別獲取到slice或者map中某個(gè)元素所在的index以及其值。

比如像這樣的用法:

for index, value := range mySlice {
 fmt.Println("index: " + index)
 fmt.Println("value: " + value)
}

上面的例子足夠清晰的描述了range的用法,實(shí)際上在使用range關(guān)鍵字的時(shí)候,還有一些需要特別注意的地方,有一些新手很容易入的”坑”。

為了說(shuō)明這些”坑”,我們可以從下面這個(gè)稍復(fù)雜的例子說(shuō)起:

type Foo struct {
 bar string
}
func main() {
 list := []Foo{
 {"A"},
 {"B"},
 {"C"},
 }
 list2 := make([]*Foo, len(list))
 for i, value := range list {
 list2[i] = value
 }
 fmt.Println(list[0], list[1], list[2])
 fmt.Println(list2[0], list2[1], list2[2])
}

在這個(gè)例子中,我們干了下面的一些事情:

     1、定義了一個(gè)叫做Foo的結(jié)構(gòu),里面有一個(gè)叫bar的field。隨后,我們創(chuàng)建了一個(gè)基于Foo結(jié)構(gòu)體的slice,名字叫l(wèi)ist

     2、我們還創(chuàng)建了一個(gè)基于Foo結(jié)構(gòu)體指針類型的slice,叫做list2

     3、在一個(gè)for循環(huán)中,我們?cè)噲D遍歷list中的每一個(gè)元素,獲取其指針地址,并賦值到list2中index與之對(duì)應(yīng)的位置。

     4、最后,分別輸出list與list2中的每個(gè)元素

從代碼來(lái)看,理所當(dāng)然,我們期望得到的結(jié)果應(yīng)該是這樣:

{A} {B} {C}
{A} {B} {C}

但是結(jié)果卻出乎意料,程序的輸出是這樣的:

{A} {B} {C}
{C} {C} {C}

從結(jié)果來(lái)看,仿佛list2中的三個(gè)元素,都指向了list中的最后一個(gè)元素。這是為什么呢?問(wèn)題就出在上面那一段for…range循環(huán)中。

在Go的for…range循環(huán)中,Go始終使用值拷貝的方式代替被遍歷的元素本身,簡(jiǎn)單來(lái)說(shuō),就是for…range中那個(gè)value,是一個(gè)值拷貝,而不是元素本身。這樣一來(lái),當(dāng)我們期望用獲取元素的指針地址時(shí),實(shí)際上只是取到了value這個(gè)臨時(shí)變量的指針地址,而非list中真正被遍歷到的某個(gè)元素的指針地址。而在整個(gè)for…range循環(huán)中,value這個(gè)臨時(shí)變量會(huì)被重復(fù)使用,所以,在上面的例子中,list2被填充了三個(gè)相同的指針地址,并且這三個(gè)地址都指向value,而在最后一次循環(huán)中,value被賦與了{c}的指針地址。因此,list2輸出的時(shí)候顯示出了三個(gè){c} 。

同樣的,下面的寫(xiě)法,跟for…range的例子如出一轍:

var value Foo
for var i := 0; i  len(list); i++ {
 value = list[i]
 list2[i] = value
}

如果我們輸出list2的三個(gè)元素,結(jié)果同樣是: {C} {C} {C}

那么,怎樣才是正確的寫(xiě)法呢?我們應(yīng)該用index來(lái)訪問(wèn)for…range中真實(shí)的元素,并獲取其指針地址:

for i, _ := range list {
 list2[i] = list[i]
}

這樣,輸出list2中的元素,就能得到我們想要的結(jié)果({A} {B} {C})了。

實(shí)驗(yàn)代碼如下:

package main

import "fmt"

type Foo struct {
 bar string
}

func main() {
 list := []Foo{
 {"A"},
 {"B"},
 {"C"},
 }

 list2 := make([]*Foo, len(list))

 //錯(cuò)誤的例子
 for i, value := range list {
 list2[i] = value
 }

 //正確的例子
 //for i, _ := range list {
 // list2[i] = list[i]
 //}

 fmt.Println(list[0], list[1], list[2])
 fmt.Println(list2[0], list2[1], list2[2])
}

了解了range的正確使用姿勢(shì),那么我們下面這個(gè)例子也能迎刃而解了:

package main
import "fmt"
type MyType struct {
 field string
}
func main() {
 var array [10]MyType
 for _, e := range array {
 e.field = "foo"
 }
 for _, e := range array {
 fmt.Println(e.field)
 fmt.Println("--")
 }
}

平常寫(xiě)代碼最常見(jiàn)的場(chǎng)景,就是我們需要在一個(gè)循環(huán)中修改被遍歷元素的值。比如上面這個(gè)例子,我們希望能使用for…range循環(huán),一次性將array中每個(gè)元素的field設(shè)置為”foo”。同樣,因?yàn)閞ange值拷貝的緣故,上面的程序什么都不會(huì)輸出……

而正確的做法是:

for i, _ := range array {
 array[i].field = "foo"
}

通過(guò)index訪問(wèn)每個(gè)元素,并修改其field,這樣,就能輸出一堆”foo”了……

實(shí)驗(yàn)代碼如下:

package main

import "fmt"

type MyType struct {
 field string
}

func main() {
 var array [10]MyType

 for i, _ := range array {
 array[i].field = "foo"
 }

 for _, e := range array {
 fmt.Println(e.field)
 }
}

總結(jié)

以上就是關(guān)于Go語(yǔ)言中Range關(guān)鍵字的全部?jī)?nèi)容,這篇文章介紹的還是很詳細(xì)的,相信本文會(huì)對(duì)大家學(xué)習(xí)Go語(yǔ)言具有一定的參考價(jià)值,如果有疑問(wèn)大家可以留言交流,小編會(huì)盡快給大家回復(fù)的,也請(qǐng)大家繼續(xù)支持腳本之家。

您可能感興趣的文章:
  • Mac OS X中設(shè)置VIM語(yǔ)法高亮的方法
  • PHP語(yǔ)法自動(dòng)檢查的Vim插件
  • vim配置顯示行號(hào)和語(yǔ)法高亮 即.vimrc文件的配置
  • 解決vim語(yǔ)法高亮不起作用的方法
  • google 搜索框添加關(guān)鍵字實(shí)現(xiàn)代碼
  • Go語(yǔ)言開(kāi)發(fā)環(huán)境搭建與初探(Windows平臺(tái)下)
  • ubuntu下搭建Go語(yǔ)言(golang)環(huán)境
  • 利用Go語(yǔ)言初步搭建一個(gè)web應(yīng)用的教程
  • go語(yǔ)言環(huán)境搭建簡(jiǎn)述
  • Centos下搭建golang環(huán)境及vim高亮Go關(guān)鍵字設(shè)置的方法

標(biāo)簽:銅川 仙桃 黃山 湘潭 蘭州 衡水 湖南 崇左

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《淺析Go語(yǔ)言中的Range關(guān)鍵字》,本文關(guān)鍵詞  ;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問(wèn)題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。
  • 相關(guān)文章
  • 收縮
    • 微信客服
    • 微信二維碼
    • 電話咨詢

    • 400-1100-266
    乐业县| 南皮县| 宁国市| 五台县| 酉阳| 汝城县| 宝丰县| 吉水县| 本溪| 桂东县| 香格里拉县| 贵德县| 靖宇县| 麟游县| 金坛市| 犍为县| 乐都县| 彝良县| 镇巴县| 攀枝花市| 海兴县| 元阳县| 自贡市| 宁晋县| 沁源县| 吐鲁番市| 达日县| 大足县| 广宁县| 铁力市| 彭阳县| 吉水县| 岚皋县| 定安县| 鲜城| 金阳县| 尉犁县| 蚌埠市| 阜平县| 依兰县| 如皋市|