はじめに
先日にアップしたはじめてのGo言語(6. 構造体)に続いて、Go言語の基礎を学んだ記録を記事としてまとめてみました。
実行環境
WSL2(Ubuntu 22.04.3 LTS)
go 1.18.1
privateな関数
- JavaやC#などでは関数名の前に
privateやpublicなどのアクセス修飾子を付けることで、関数の可視性をコントロールできます。 - Go言語にも同様の仕組みがあるだろうと考えて調べてみると、[golang]プライベート関数の定義方法には以下のように書かれていました。
プライベートな関数は、次のように関数名を小文字で始めて定義します。
- 「関数名の先頭が小文字であればプライベート関数になる」という言語は初めてなので驚きましたが、「コーディング時に手数を減らしたい」という方には良い仕組みなのかもしれません。
- 私は
privateなどアクセス修飾子を付けて明示した方が間違いが少ないと思いますが、ここは好みの違いなのかもしれません...
- 私は
privateな構造体
- 同様に構造体の可視性について調べてみると、とほほのGo言語入門には以下のように書かれていました。
構造体のメンバの内、大文字で始まるものはパッケージ外からアクセス可能、小文字で始まるものはパッケージ外からアクセス不可となります。
- 関数と同様に、「構造体もメンバ変数名の先頭が小文字であればプライベートになる」というのは驚きでした。
- 構造体でアクセス修飾子を使ってしまうと言語全体で統一性がなくなるので、関数と構造体で同じルールを適用しているのかもしれません。
関数と構造体のprivate/public
フォルダ構成
- 関数と構造体の可視性について確認するため、以下のフォルダ構成でコードを作成しました。
フォルダ構成
/mnt/c/Users/NKOJIMA/golang/test
├── access.go
├── go.mod
└── /corp
└── emp.go
コードの作成
emp.go
-
emp.goに、プライベートな関数(printNote)とプライベートなメンバ変数を持つ構造体(Employee)を作ります。 - パッケージ名はフォルダ名と同じにしています。
- パッケージ名とフォルダ名を異なる文字列にすると、どうも上手く動かないようです。
- フォルダ名とパッケージ名は、おそらく予約語などに引っかからなければ何でも大丈夫だと思います。
emp.go
package corp
import "fmt"
// 従業員を表す構造体
type Employee struct {
Name string
Id int
note string // privateなメンバ変数
}
// 従業員名を表示する
func (emp *Employee) PrintName() {
fmt.Printf("名前:%s\n", emp.Name)
}
// 備考を表示する(privateな関数)
func (emp *Employee) printNote() {
fmt.Printf("備考:%s\n", emp.note)
}
access.go
-
access.goには、private.goに定義した関数や構造を呼び出すコードを記述します。 - 呼び出したいパッケージ(
main/corp)を指定する際には、このパッケージから見た相対的なフォルダ位置を記述するようです。- この点については、きちんと書かれている資料が見つけられませんでした...
access.go
package main
import "main/corp"
func main() {
var emp corp.Employee
emp.Name = "nkojima"
emp.Id = 1234
// emp.note = "テスト" // privateなメンバ変数にはアクセスできない
emp.PrintName()
// emp.printNote() // privateな関数にはアクセスできない
}
go.modの作成
- 単純に
access.goを実行すると、パッケージ"main/corp"をインポートできずにエラーとなるため、ここではgo.modという「モジュールの依存関係のルートとなるファイル」を作ります。
go.modが無い状態でacccess.goを実行
# go run access.go
access.go:3:8: package main/corp is not in GOROOT (/usr/lib/go-1.18/src/main/corp)
-
go mod init {パッケージ名}でgo.modを作成します。
go.modの作成
# pwd
/mnt/c/Users/NKOJIMA/golang/test
# go mod init main
go: creating new go.mod: module main
go: to add module requirements and sums:
go mod tidy
- 出来上がった
go.modはやたらシンプルな中身で、ちょっと不安になりましたがこれで正しいようです。
go.mod
module main
go 1.18
プログラムの実行
-
go.modを作ってからaccess.goを実行すると、以下のように正常に実行できました。
実行結果
# go run access.go
名前:nkojima
-
access.goでプライベートなメンバ変数(emp.note)にアクセスする箇所をアンコメントすると、以下のようにエラーが発生します。
実行結果(privateなメンバ変数にアクセス)
# go run access.go
# command-line-arguments
./access.go:10:9: emp.note undefined (type corp.Employee has no field or method note)
- また、
access.goでプライベートな関数(emp.printNote)にアクセスする箇所をアンコメントすると、以下のようにエラーが発生します。
実行結果(privateな関数にアクセス)
# go run access.go
# command-line-arguments
./access.go:13:9: emp.printNote undefined (type corp.Employee has no field or method printNote)