Go 中的複合字面量

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。![](https://raw.githubusercontent.com/studygolang/gctt-images/master/composite-literal/1_TM61VTlvvL2YWtI6UUYLOg.png)在原始碼中字面量可以描述像數字,字串,布爾等類型的固定值。Go 和 JavaScript、Python 語言一樣,即便是複合類型(數組,字典,切片,結構體)也允許使用字面量。Golang 的複合字面量表達也很方便、簡潔,使用單一文法即可實現。在 JavaScript 中它是這樣的:```javascriptvar numbers = [1, 2, 3, 4]var thing = {name: "Raspberry Pi", generation: 2, model: "B"}```在 Python 中有類似的文法:```pythonelements = [1, 2, 3, 4]thing = {"name": "Raspberry Pi", "generation": 2, "model": "B"}```在 Go 中也類似(這裡有些地方可以變通):```goelements := []int{1, 2, 3, 4}type Thing struct {name stringgeneration intmodel string}thing := Thing{"Raspberry Pi", 2, "B"}// 或者直接使用結構體的項名稱thing = Thing{name: "Raspberry Pi", generation: 2, model: "B"}```除了字典類型以外的其他類型,鍵是可選的,便於理解沒有歧義:* 對結構體而言,鍵就是項名稱* 對於數組或切片而言,鍵就是索引 鍵不是字面量常量,就必須是常量運算式;因此這種寫法是錯誤的:```gof := func() int { return 1 }elements := []string{0: "zero", f(): "one"}```這將導致編譯異常 -- "index must be non-negative integer constant"。而常量運算式或者字面量是合法的:```goelements := []string{0: "zero", 1: "one", 4 / 2: "two"}```編譯一切順利。 重複的鍵是不允許的:```goelements := []string{0: "zero",1: "one",4 / 2: "two",2: "also two"}```在編譯時間會報出 "duplicate index in array literal: 2" 的異常資訊。這也同樣適用於結構體:```gotype S struct {name string}s := S{name: "Michał", name: "Michael"}```編譯結果是 "duplicate field name in struct literal: name" 的錯誤。相應的字面量必須被賦值給相應的鍵,元素或結構體的項。更多關於可賦值性的內容可查看 ["Go 語言中的可賦值性"](https://studygolang.com/articles/12381)一文。## 結構體對於結構體類型定義的項,這裡有兩三個建立執行個體時的規定。像下面的程式碼片段,結構體的定義必須指定內部項的名稱,並且如果使用了那些定義以外的名稱,那麼在編譯時間會發生錯誤:"unknown S field ‘name’ in struct literal":```gotype S struct {age int8}s := S{name: "Michał"}```如果最先的字面量有對應的鍵,那麼之後的字面量也必須有對應的鍵,下面這樣寫是不合理的:```gotype S struct {name stringage int8}s := S{name: "Michał", 29}```像這樣,編譯器會拋出異常"mixture of field:value and value initializers",可以通過省略結構體中所有元素對應的鍵來更正它。```gos := S{"Michał", 29}```但這樣又有一個附加限制:字面量的依次順序必須與結構體定義時各項的順序保持一致。 必須使用鍵:值或值的形式初始化結構體,並不代表我們必須賦值結構體中的每一項。被忽略的項將會預設賦值為該項類型對應的零值:```gotype S struct {name stringage int8}s := S{name: "Michał"}fmt.Printf("%#v\n", s)```輸出:```gomain.S{name:"Michał", age:0}```只有使用鍵:值的形式初始化結構體時,才會有預設賦零值的操作:```gos := S{"Michał"}```這種寫法是不能編譯通過的,會拋出異常"too few values in struct initializer"。當有新的項被添加到結構體的一個被字面量賦值的項之前時,這種報錯的做法對程式員更加安全--如果這個結構體中,一個名為"title"的字串類型的項被加到了"name"項之前,那麼值"Michał"將被認為是一個"title",而這個問題是很難被排查出來的。 如果結構體字面量是空值,那麼結構體內每一項都會被賦於零值:```gotype Employee struct {department stringposition string}type S struct {name stringage int8Employee}main.S{name:"", age:0, Employee:main.Employee{department:"", position:""}}```最後一個規定,結構體的賦值與[匯出標示](https://studygolang.com/articles/12809)有關(簡而言之,字面量不允許給非匯出項賦值)## 數組和切片數組或者切片的元素都是被索引的,所以在字面上鍵必須是整數常量運算式。對於沒有鍵的元素,鍵將會被賦值為前一個元素索引加一。在字面上,第一個元素的鍵(索引)如果沒有被賦值,預設設為零。 ```gonumbers := []string{"a", "b", 2 << 1: "c", "d"}fmt.Printf("%#v\n", numbers)[]string{"a", "b", "", "", "c", "d"}```賦值元素的數量可以小於數組的長度(被忽略的元素將會被賦值為零):```gofmt.Printf("%#v\n", [3]string{"foo", "bar"})[3]string{"foo", "bar", ""}```不允許對超出範圍的索引賦值,所以下面幾行代碼是無效的:```[1]string{"foo", "bar"}[2]string{1: "foo", "bar"}```可以通過使用三個點(...)的快捷符號來省去程式員聲明數組長度的工作,編譯器會通過索引最大值加一的方式獲得它:```goelements := […]string{2: "foo", 4: "bar"}fmt.Printf("%#v, length=%d\n", elements, len(elements))```輸出:```[5]string{"", "", "foo", "", "bar"}, length=5```切片與之前數組內容基本一致:```goels := []string{2: "foo", 4: "bar"}fmt.Printf("%#v, length=%d, capacity=%d\n", els, len(els), cap(els))```得出結果:```[]string{"", "", "foo", "", "bar"}, length=5, capacity=5```## 字典除了將數組長度替換成了鍵類型以外,字典字面量的文法和數組非常類似。```goconstants := map[string]float64{"euler": 2.71828, "pi": .1415926535}```## 捷徑如果作為字典鍵或者數組、切片、字典元素的字面量的類型與鍵或元素的類型一致,那麼為了簡潔,這個類型可以省略不寫:```gocoords := map[[2]byte]string{{1, 1}: "one one", {2, 1}: "two one"}type Engineer struct {name stringage byte}engineers := [...]Engineer{{"Michał", 29}, {"John", 25}}```同樣,如果鍵或元素是指標類型的話,&T也可以被省略:```goengineers := […]*Engineer{{"Michał", 29}, {"John", 25}}fmt.Printf("%#v\n", engineers)```輸出:```[2]*main.Engineer{(*main.Engineer)(0x8201cc1e0), (*main.Engineer)(0x8201cc200)}```## 資源https://golang.org/ref/spec#Composite_literals

via: https://medium.com/golangspec/composite-literals-in-go-10dc62eec06a

作者:Michał Łowicki 譯者:yiyulantian 校對:polaris1119

本文由 GCTT 原創編譯,Go語言中文網 榮譽推出

本文由 GCTT 原創翻譯,Go語言中文網 首發。也想加入譯者行列,為開源做一些自己的貢獻嗎?歡迎加入 GCTT!
翻譯工作和譯文發表僅用於學習和交流目的,翻譯工作遵照 CC-BY-NC-SA 協議規定,如果我們的工作有侵犯到您的權益,請及時聯絡我們。
歡迎遵照 CC-BY-NC-SA 協議規定 轉載,敬請在本文中標註並保留原文/譯文連結和作者/譯者等資訊。
文章僅代表作者的知識和看法,如有不同觀點,請樓下排隊吐槽

529 次點擊  
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.