網頁

2021/6/12

Golang Exported names 匯出名稱

Go語言使用exported name(匯出名稱)讓外部存取,也就是能被其他package程式呼叫。


Java是以存取修飾符(access modifiers)定義類別的成員是否可被外部存取,例如public修飾可被其他package的類別存取,private則僅限內部使用,這概念又稱為封裝(Encapsulation)


Go則以開頭名稱的大小寫決定package內的特性是否能被外部存取:
大寫開頭(upper case, exported name)可被其他package存取,
小寫開頭(lower case, unexported name)限package內使用。


在「Golang 建立Go module」範例中greetings package的Hello()函式為大寫開頭,因此可被main package的main.go程式被呼叫。若在greeting.go定義一個小寫開頭的函式hi(),則此函式無法被其他package呼叫。

greeting.go

package greetings

func Hello(name string) string { // 大寫開頭 exported
    message := "Hello " + name
    return message
}

func hi(name string) string { // 小寫開頭 unexported
    message := "Hi " + name
    return message
}

main.go試著呼叫greetings.hi()執行時會發生 cannot refer to unexported name greetings.hi錯誤。

main.go

package main

import (
    "fmt"
    "abc.com/greetings"
)

func main() {

    message := greetings.Hello("John")
    fmt.Println(message)
    
    message = greetings.hi("Mary") // cannot refer to unexported name greetings.hi
    fmt.Println(message)
}


exported name可決定type能被其他package使用。例如在greeting.go宣告一個Count型態為int type。

greeting.go

package greetings

type Count int // exported
...

main.go可正常使用greetings.Count

main.go

package main

import (
    "fmt"
    "abc.com/greetings"
)

func main() {

    count := greetings.Count(1)
    fmt.Println(count) // 1
    ...
}

若把Count改為小寫count則出現錯誤。

greeting.go

package greetings

type count int // unexported
...

main.go

package main

import (
    "fmt"
    "abc.com/greetings"
)

func main() {

    count := greetings.count(1) // cannot refer to unexported name greetings.count
    fmt.Println(count)
    ...
}


exported name也可以決定struct型別的屬性能被其他package存取。例如在greeting.go宣告一個Person struct type。

greeting.go

package greetings
...
type Person struct {
    Name string  // 大寫開頭 exported
    Title string // 大寫開頭 exported
    age int      // 小寫開頭 unexported
}
...

main.go建立greetings.Person時只能存取大寫開頭的屬性,存取小寫屬性會發生cannot refer to unexported field in struct literal錯誤。

main.go

package main

import (
    "fmt"
    "abc.com/greetings"
)

func main() {
    ...
    person := greetings.Person {
        Name: "Dave",
        Title: "Dr.",
        age: 50,      // cannot refer to unexported field 'age' in struct literal of type greetings.Person
    }
    ...
}


沒有留言:

張貼留言