Go語言中常見100問題-#1 小心變量遮蔽

小心變量遮蔽

變量的作用域是指一個(gè)變量可以被引用的地方/范圍。換句話說,就是應(yīng)用程序的一個(gè)區(qū)域,在該區(qū)域內(nèi)變量是有效的,超出該區(qū)域便無效。在Go語言中,在代碼塊中聲明的變量可以在內(nèi)部代碼塊中重新聲明,這種使用方法稱為變量遮蔽/隱藏,注意在使用時(shí)要非常小心,否則很容易出現(xiàn)常見的錯(cuò)誤。下面通過一個(gè)具體的程序例子說明變量遮蔽/隱藏導(dǎo)致的問題,程序中將以兩種不同的方式創(chuàng)建 HTTP 客戶端,具體采用哪種方式依賴于變量tracing的值。

var client *http.Client
if tracing {
        client, err := createClientWithTracing()
        if err != nil {
                return err
        }
        log.Println(client)
} else {
        client, err := createDefaultClient()
        if err != nil {
                return err
        }
        log.Println(client)
}
// Use client

上面的程序首先定義了一個(gè)客戶端變量client, 然后在兩個(gè)內(nèi)部代碼塊中使用短變量聲明運(yùn)算符(:=)賦值,雖然賦值給的變量也是client,但是它與外面的client不是同一個(gè),因此,執(zhí)行上述程序外部的client始終為nil.

NOTE: 上面的代碼可以編譯通過,因?yàn)閮?nèi)部賦值的client變量在log.Println中使用到了,否則的話,將出現(xiàn)編譯錯(cuò)誤,提示client(內(nèi)部的)聲明但未使用。

如何修復(fù)上面代碼中存在的問題呢?有兩種不同的方法。方法一是在內(nèi)部代碼塊中使用一個(gè)臨時(shí)變量保存client,此臨時(shí)變量名不要使用client,然后再將臨時(shí)變量值賦值給client, 實(shí)現(xiàn)代碼如下。這里先將結(jié)果保存在臨時(shí)變量c中,c的作用域在if塊中,最后再將c賦值給客戶端變量client.

var client *http.Client
if tracing {
        c, err := createClientWithTracing()
        if err != nil {
                return err
        }
        client = c
} else {
        // Same logic
}

方法二是使用賦值運(yùn)算符(=)將創(chuàng)建結(jié)果直接分配給客戶端變量client,但是需要?jiǎng)?chuàng)建一個(gè)錯(cuò)誤變量,因?yàn)橘x值運(yùn)算符(=)對(duì)已聲明的變量才能使用。然后直接將創(chuàng)建結(jié)果分配給client,實(shí)現(xiàn)如下。

var client *http.Client
var err error
if tracing {
        client, err = createClientWithTracing()
        if err != nil {
                return err
        }
} else {
        // Same logic
}

上述兩種方法都是正確的,主要區(qū)別在于方法二種只執(zhí)行了一個(gè)賦值操作,閱讀起來可能更容易。此外,使用方法二,可以在if/else語句之后統(tǒng)一對(duì)錯(cuò)誤進(jìn)行處理。

if tracing {
        client, err = createClientWithTracing()
} else {
        client, err = createDefaultClient()
}
if err != nil {
        // Common error handling
}

總結(jié),在內(nèi)部代碼塊中重新聲明變量時(shí),會(huì)產(chǎn)生變量遮蔽/隱藏,通過前面的例子可以看到這種做法很容易出錯(cuò)。所以在編碼中,注重代碼品味,盡量不要犯變量遮蔽/隱藏問題。雖然有時(shí)重用現(xiàn)有變量會(huì)非常方便,例如在用err表示錯(cuò)誤時(shí)。但是,總體來說,我們應(yīng)該謹(jǐn)慎小心,否則很容易出現(xiàn)問題,像本文舉的例子,接收到值的變量不是我們預(yù)期的變量。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容