iota: Golang 中優雅的常量

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

註:該文作者是 Katrina Owen,原文地址是 iota: Elegant Constants in Golang

有些概念有名字,並且有時候我們關注這些名字,甚至(特別)是在我們代碼中。

const (    CCVisa            = "Visa"    CCMasterCard      = "MasterCard"    CCAmericanExpress = "American Express")

在其他時候,我們僅僅關注能把一個東西與其他的做區分。有些時候,有些時候一件事沒有本質上的意義。比如,我們在一個資料庫表中儲存產品,我們可能不想以 string 儲存他們的分類。我們不關注這個分類是怎樣命名的,此外,該名字在市場上一直在變化。

我們僅僅關注它們是怎麼彼此區分的。

const (    CategoryBooks    = 0    CategoryHealth   = 1    CategoryClothing = 2)

使用 0, 1, 和 2 代替,我們也可以選擇 17, 43, 和 61。這些值是任意的。

常量是重要的,但是它們很難推斷,並且難以維護。在一些語言中像 Ruby 開發人員通常只是避免它們。在 Go,常量有許多微妙之處。當用好了,可以使得代碼非常優雅且易維護的。

自增長

在 golang 中,一個方便的習慣就是使用 iota 標示符,它簡化了常量用於增長數位定義,給以上相同的值以準確的分類。

const (    CategoryBooks = iota // 0    CategoryHealth       // 1    CategoryClothing     // 2)

自訂類型

自增長常量經常包含一個自訂類型,允許你依靠編譯器。

type Stereotype intconst (    TypicalNoob Stereotype = iota // 0    TypicalHipster                // 1    TypicalUnixWizard             // 2    TypicalStartupFounder         // 3)

如果一個函數以 int 作為它的參數而不是 Stereotype,如果你給它傳遞一個 Stereotype,它將在編譯器期出現問題。

func CountAllTheThings(i int) string {                return fmt.Sprintf("there are %d things", i)}func main() {    n := TypicalHipster    fmt.Println(CountAllTheThings(n))}// output:// cannot use TypicalHipster (type Stereotype) as type int in argument to CountAllTheThings

相反亦是成立的。給一個函數以 Stereotype 作為參數,你不能給它傳遞 int

func SoSayethThe(character Stereotype) string {    var s string    switch character {    case TypicalNoob:        s = "I'm a confused ninja rockstar."    case TypicalHipster:        s = "Everything was better we programmed uphill and barefoot in the snow on the SUTX 5918"    case TypicalUnixWizard:        s = "sudo grep awk sed %!#?!!1!"    case TypicalStartupFounder:        s = "exploit compelling convergence to syndicate geo-targeted solutions"    }    return s}func main() {    i := 2    fmt.Println(SoSayethThe(i))}// output:// cannot use i (type int) as type Stereotype in argument to SoSayethThe

這是一個戲劇性的轉折,儘管如此。你可以傳遞一個數值常量,然後它能工作。

func main() {    fmt.Println(SoSayethThe(0))}// output:// I'm a confused ninja rockstar.

這是因為常量在 Go 中是弱類型直到它使用在一個嚴格的上下文環境中。

Skipping Values

設想你在處理消費者的音訊輸出。音頻可能無論什麼都沒有任何輸出,或者它可能是單聲道,立體聲,或是環繞立體聲的。

這可能有些潛在的邏輯定義沒有任何輸出為 0,單聲道為 1,立體聲為 2,值是由通道的數量提供。

所以你給 Dolby 5.1 環繞立體聲什麼值。

一方面,它有6個通道輸出,但是另一方面,僅僅 5 個通道是全頻寬通道(因此 5.1 稱號 - 其中 .1 表示的是低頻效果通道)。

不管怎樣,我們不想簡單的增加到 3。

我們可以使用底線跳過不想要的值。

type AudioOutput intconst (    OutMute AudioOutput = iota // 0    OutMono                    // 1    OutStereo                  // 2    _    _    OutSurround                // 5)

運算式

iota 可以做更多事情,而不僅僅是 increment。更精確地說,iota 總是用於 increment,但是它可以用於運算式,在常量中的儲存結果值。

這裡我們建立一個常量用於位元遮罩。

type Allergen intconst (    IgEggs Allergen = 1 << iota // 1 << 0 which is 00000001    IgChocolate                         // 1 << 1 which is 00000010    IgNuts                              // 1 << 2 which is 00000100    IgStrawberries                      // 1 << 3 which is 00001000    IgShellfish                         // 1 << 4 which is 00010000)

這個工作是因為當你在一個 const 組中僅僅有一個標示符在一行的時候,它將使用增長的 iota 取得前面的運算式並且再運用它,。在 Go 語言的 spec 中, 這就是所謂的隱性重複最後一個非空的運算式列表。

如果你對雞蛋,巧克力和海鮮過敏,把這些 bits 翻轉到 “on” 的位置(從左至右映射 bits)。然後你將得到一個 bit 值 00010011,它對應十進位的 19。

fmt.Println(IgEggs | IgChocolate | IgShellfish)// output:// 19

這是在 Effective Go 中一個非常好定義數量級的樣本:

type ByteSize float64const (    _           = iota                   // ignore first value by assigning to blank identifier    KB ByteSize = 1 << (10 * iota) // 1 << (10*1)    MB                                   // 1 << (10*2)    GB                                   // 1 << (10*3)    TB                                   // 1 << (10*4)    PB                                   // 1 << (10*5)    EB                                   // 1 << (10*6)    ZB                                   // 1 << (10*7)    YB                                   // 1 << (10*8))

今天我學習到了在 zettabyte 之後是 yottabyte。

但是等等,這有更多

當你在把兩個常量定義在一行的時候會發生什嗎?
Banana 的值是什嗎? 2 還是 3? Durian 的值又是?

const (    Apple, Banana = iota + 1, iota + 2    Cherimoya, Durian    Elderberry, Fig)

iota 在下一行增長,而不是立即取得它的引用。

// Apple: 1// Banana: 2// Cherimoya: 2// Durian: 3// Elderberry: 3// Fig: 4

這搞砸了,因為現在你的常量有相同的值。

因此,對的

在 Go 中,關於常量有很多東西可以說,你應該在 golang 部落格讀讀 Rob Pike 的這篇文章。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.