Go語言實戰筆記(十一)| Go 標誌符可見度

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

《Go語言實戰》讀書筆記,未完待續,歡迎掃碼關注公眾號flysnow_org,第一時間看後續筆記。覺得有協助的話,順手分享到朋友圈吧,感謝支援。

Go的標誌符,這個翻譯覺得怪怪的,不過還是按這個起了標題,可以理解為Go的變數、類型、欄位等。這裡的可見度,也就是說那些方法、函數、類型或者變數欄位的可見度,比如哪些方法不想讓另外一個包訪問,我們就可以把它們聲明為非公開的;如果需要被另外一個包訪問,就可以聲明為公開的,和Java語言裡的範圍類似。

在Go語言中,沒有特別的關鍵字來聲明一個方法、函數或者類型是否為公開的,Go語言提供的是以大小寫方式進行區分的,如果一個類型的名字是以大寫開頭,那麼其他包就可以訪問;如果以小寫開頭,其他包就不能訪問。

123
package commontype count int
1234567891011
package mainimport ("flysnow.org/hello/common""fmt")func main() {c:=common.count(10)fmt.Println(c)}

這是一個定義在common包裡的類型count,因為它的名字以小寫開頭,所以我們不能在其他包裡使用它,否則就會報編譯錯誤。

1
./main.go:9: cannot refer to unexported name common.count

因為這個類型沒有被匯出,如果我們改為大寫,就可以正常編譯運行了,大家可以自己試試。

現在這個類型沒有匯出,不能使用,現在我們修改下例子,增加一個函數,看看是否可行。

1234567
package commontype count intfunc New(v int) count {return count(v)}
1234
func main() {c:=common.New(100)fmt.Println(c)}

這裡我們在common包裡定義了一個匯出的函數New ,該函數返回一個count類型的值。New函數可以在其他包訪問,但是count類型不可以,現在我們在main包裡調用這個New函數,會發現是可以正常調用並且啟動並執行,但是有個前提,必須使用:=這樣的操作符才可以,因為它可以推斷變數的類型。

這是一種非常好的能力,試想,我們在和其他人進行函數方法通訊的時候,只需約定好介面,就可以了,至於內部實現,使用方是看不到的,隱藏了實現。

1234567891011121314151617
package commonimport "fmt"func NewLoginer() Loginer{return defaultLogin(0)}type Loginer interface {Login()}type defaultLogin intfunc (d defaultLogin) Login(){fmt.Println("login in...")}
1234
func main() {l:=common.NewLoginer()l.Login()}

以上例子,我們對於函數間的通訊,通過Loginer介面即可,在main函數中,使用者只需要返回一個Loginer介面,至於這個介面的實現,使用者是不關心的,所以介面的設計者可以把defaultLogin類型設計為不可見,並讓它實現介面Loginer,這樣我們就隱藏了具體的實現。如果以後重構這個defaultLogin類型的具體實現時,也不會影響外部的使用者,極為方便,這也就是面向介面的編程。

假如一個匯出的結構體類型裡,有一個未匯出的欄位,會出現怎樣的問題。

1234
type User struct {Name stringemail string}

當我們在其他包聲明和初始化User的時候,欄位email是無法初始化的,因為它沒有匯出,無法訪問。此外,一個匯出的類型,包含了一個未匯出的方法也一樣,也是無法訪問的。

我們再擴充,匯出和未匯出的類型相互嵌入,會有什麼什麼樣的發現?

1234567
type user struct {Name string}type Admin struct {user}

被嵌入的user是未匯出的,但是它的外部類型Admin是匯出的,所以外部可以聲明初始化Admin

12345
func main() {var ad common.Adminad.Name="張三"fmt.Println(ad)}

這裡因為user是未匯出的,所以我們不能再使用字面值直接初始化user了,所以只能先定義一個Admin類型的變數,再對Name欄位初始化。這裡Name可以訪問是因為它是匯出的,在user嵌入到Admin中時,它已經被提升為Admin的欄位,所以它可以被訪問。

如果我們還想使用:=操作符怎麼做呢?

1
ad:=common.Admin{}

字面值初始化的時候什麼都不做就好了,因為user未匯出,所以我們不能直接使用字面值初始化Name欄位。

還有要注意的是,因為user未匯出,所以我們不能通過外部類型訪問內部類型了,也就是說ad.user這樣的操作,都會編譯不通過。

最後,我們做個總結,匯出還是未匯出,是通過名稱首字母的大小寫決定的,它們決定了是否可以訪問,也就是標誌符的可見度。

對於.操作符的調用,比如調用類型的方法,包的函數,類型的欄位,外部類型訪問內部類型等等,我們要記住:.操作符前面的部分匯出了,.操作符後面的部分才有可能被訪問;如果.前面的部分都沒有匯出,那麼即使.後面的部分是匯出的,也無法訪問。

例子 可否訪問
Admin.User.Name
Admin.User.name
Admin.user.Name
Admin.user.name

以上表格中Admin 為外部類型,User(user)為內部類型,Name(name)為欄位,以此來更好的理解最後的總結,當然方法也適用這個表格。

《Go語言實戰》讀書筆記,未完待續,歡迎掃碼關注公眾號flysnow_org,第一時間看後續筆記。覺得有協助的話,順手分享到朋友圈吧,感謝支援。

聯繫我們

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