Go學習筆記 struct的匯出

2022-04-11 07:02:03 字數 3945 閱讀 9933

struct的屬性是否被匯出,也遵循大小寫的原則:首字母大寫的被匯出,首字母小寫的不被匯出。

所以:如果struct名稱首字母是小寫的,這個struct不會被匯出。連同它裡面的字段也不會匯出,即使有首字母大寫的欄位名

如果struct名稱首字母大寫,則struct會被匯出,但只會匯出它內部首字母大寫的字段,那些小寫首字母的字段不會被匯出

也就是說,struct的匯出情況是混合的。

但並非絕對如此,如果struct巢狀了,那麼即使被巢狀在內部的struct名稱首字母小寫,也能訪問到它裡面首字母大寫的字段

例如:

type animal struct

type horse struct

horse中巢狀的animal是小寫字母開頭的,但horse是能被匯出的,所以能在其它包中使用horse struct,其他包也能訪問到animal中的speak屬性。

很多時候,horse這個名字是不安全的,因為這表示匯出horse這個struct給其他包,也就是將horse給暴露出去了,外界可以直接開啟horse這個"黑匣子"。

但如果不將horse匯出,如何能在其它包構建出horse例項?見下文。

很多時候,不應該將某包(如包abc)中的struct(如animal)直接暴露給其它包,暴露意味著開啟了那個"黑匣子",所以struct會以小寫字母開頭,不將其匯出。

這時在外界其它包中構建包abc的animal,就沒法直接通過以下幾種方式實現:

例如,下面的是錯誤的:

// abc/abc.go檔案內容:
package abc

type animal struct

// test.go內容:

package main

import "./abc"

func main()

t4 := abc.animal{}

}

那麼如何在外界構建隱藏起來的struct例項?這時可以在abc包中寫乙個可匯出的函式,通過這個函式來構建struct例項。例如:

// abc/abc.go檔案內容:

package abc

type animal struct

func newanimal() *animal

// test.go內容:

package main

import (

"fmt"

"./abc"

)func main()

上面的**一切正常,在main包中可以通過newanimal()構建出abc包中未匯出的animal struct。注意,上面newanimal()中是使用new()函式構造例項的,它返回的是例項的指標,至於如何構造例項,完全可以根據自己的需求,但對於struct型別來說,一般都是使用指標的,也就是完全可以將new()通用化。

由於animal中的name欄位是不匯出的字段,所以在外界即便是通過newanimal()構建出了animal例項,也無法訪問該例項的name屬性,所以沒法為name欄位賦值。換句話說,name屬性永遠是初始化的0值。

因此,為了讓構建例項時自定義name屬性,需要在構造方法newanimal()上指定設定給name屬性的引數。修改newanimal()函式:

func newanimal(name string) *animal

然後在其它包中構建animal例項:

t1 := abc.newanimal("longshuai")

雖然其它包中構建的animal例項已經具備了name屬性,但還是無法訪問該例項的name屬性。所以,在abc包中繼續寫乙個可匯出的方法,該方法用於獲取例項的name屬性:

// abc/abc.go中新增:

func (a *animal) getname() string

於是外界包中可以通過這個匯出的方法獲取例項的name屬性:

t1 := abc.newanimal("longshuai")

fmt.println(t1.getname())

完整示例:

main.go----

package main

import (

"fmt"

"./abc"

)func main()

abc.go----

package abc

type animal struct

func newanimal(name string) *animal

// abc/abc.go中新增:

func (a *animal) getname() string

實際上,上面newanimal()構造物件時,可以不用傳遞name引數,而是像getname()一樣,寫乙個專門的可匯出方法來設定例項的name屬性。改寫abc/abc.go中的**:

func newanimal() *animal

func (a *animal) setname(name string)

現在,abc/abc.go中的animal struct就完全對外隱藏了。

但需要注意的是,上面的setter類方法setname()不能同時被2個或多個執行緒修改,否則值被覆蓋,出現執行緒安全問題,可以使用sync包或者goroutine和channel來解決這個問題。

當內部struct巢狀進外部struct時,內部struct的方法也會被巢狀,也就是說外部struct擁有了內部struct的方法。

但是需要注意方法的首字母大小寫問題。由於內、外struct在同一包內,所以直接在該包內構建外部struct例項,外部struct例項是可以直接訪問內部struct的所有方法的。但如果在其它包內構建外部struct例項,該例項將無法訪問內部struct中首字母小寫的方法

以下是在同乙個包內測試,外部例項可以直接呼叫內部struct的方法:

package main

import (

"fmt"

)type person struct

// 未匯出方法

func (p *person) speak()

// 匯出的方法

func (p *person) sing()

// admin exported

type admin struct

func main()

執行結果時a.speak()a.sing()都正常輸出。

以下是不同包內測試,struct定義在abc/abc.go檔案中,main在test.go中,它們的目錄結構如下:

$ tree .

.├── abc

│ └── abc.go

├── test.go

abc/abc.go的內容為:

package abc

import "fmt"

// 未匯出的person

type person struct

// 未匯出的方法

func (p *person) speak()

// 匯出的方法

func (p *person) sing()

// admin exported

type admin struct

test.go的內容為:

package main

import "./abc"

func main()

執行結果是,a.speak()報錯,但a.sing()正常。

Go學習筆記(11)Go結構體struct

go的結構體是一種復合型別,它由一系列屬性 字段 組成,每個屬性 字段 都有自己的型別和值。結構體的字段可以是任何型別,甚至是結構體本身 函式 介面等 在go中沒有類的概念,因此結構體經常被用來替代物件導向中的類的操作 結構體的定義格式如下 type structname struct 下面是乙個結...

go語言學習筆記 struct結構體

理解 用來自定義資料結構,把需要的有關聯的字段集合到一起,有點型別map的key value形式,還支援巢狀 宣告乙個結構體並使用 宣告 type stu struct stu1 stu 不需要指定欄位的使用方式 stu2 stu fmt.println stu1,stu2 輸出 忽略欄位名的情況下...

Golang學習筆記(六) struct

struct struct,一組欄位的集合,類似其他語言的class 放棄了大量包括繼承在內的物件導向特性,只保留了組合 composition 這個最基礎的特性 1.宣告及初始化 複製 如下 type person struct 初始化 func main fmt.println p1.name ...