対象者
Goやりたいですってなった時
「そうだ! Go Tourやろう!」
となる人はGo Tourやってください。
他の言語でプログラミングしたことあって、Go気になってるって人向けです。
環境
- Mac
- Go1.18
下準備
go mod init github.com/yourname/example
パッケージの作成
パッケージは他の言語でいうモジュールです。
今回は2x2行列を実装します。
2x2行列は4つの整数を持ち、積を計算する Multiple
メソッドを持つものとします。
mkdir matrix
vim matrix/matrix.go
package matrix
type (
Matrix2D struct {
// a, b
// c, d
a, b, c, d int
}
)
func New(a, b, c, d int) Matrix2D {
return Matrix2D{a, b, c, d}
}
func (m Matrix2D) Multiple(n Matrix2D) Matrix2D {
a := m.a*n.a + m.b*n.c
b := m.a*n.b + m.b*n.d
c := m.c*n.a + m.d*n.c
d := m.c*n.b + m.d*n.d
return New(a, b, c, d)
}
Goにはクラスはありません。
代わりに構造体を struct
キーワードで定義します
構造体のMatrix2Dは a,b,c,d の4つのintをプロパティとして持ちます。
Goではメソッドは構造体定義と別で書きます。
上記のコードで Mutltiple
メソッドはMatrix2Dのメソッドとして定義されます。
func (m Matrix2D) Multiple
みたいに func
キーワードとメソッド名の間に (m Matrix2D)
という記述をすることで
構造体のメソッドとして定義されます。
この m
はなんでも良いです。 (matrix Matirix2D)
など。
メソッド内で自身の構造体を参照する時に使われるのがここで記述した m
です。
他の言語では self
や this
みたいに予約語とされていますが、Goではエンジニアが自分で名前を定義します。
これをレシーバー引数と言います。
最後に New
関数を見てみましょう。
これはレシーバー引数が定義されていないので、構造体のメソッドではありません。
これはmatrixパッケージに定義された関数です。
これをどうやって呼び出すかは後述します。
Goコードの大文字小文字について
Goでは先頭が大文字ならパブリック、小文字ならプライベートとなります。
プライベートなものは同じパッケージないからしかアクセスできません。
package matrix
var (
PublicVar int
privateVar int
)
func PublicFuncName() string { return privateFuncName() } // パッケージ内ではprivateFuncNameを呼び出せる。
func privateFuncName() string { return "080-XXXX-OOOO" }
ファイルとパッケージについて
matrixディレクトリに二つのファイルがあるとします。
/matrix / matrix.go
/ determinant.go
同一パッケージ内のものは別ファイルからも参照できます。
package matrix
var (
hello string // プライベート変数。
)
type Matrix2D struct { a,b,c,d int }
package matrix
import "fmt"
// ファイルdeterminant.go内では Matrix2D構造体は定義されていないが、型を参照できる。
func (m Martrix2D) determinant() int {
fmt.Println(hello) // hello変数はファイルdeterminant.go内では定義されていないが参照できる。
// Snip...
}
パッケージを使用する。
ディレクトリ構成
main.go
matirx / matrix.go
/ determinant.go
main.goを作成して、matrixパッケージのコードを呼び出します。
package main
import (
"fmt"
"github.com/yourname/example/matrix"
)
func main() {
m := matrix.New(1,2,3,4)
n := matrix.New(2,4,6,8)
fmt.Prtinln(m.Multiple(m))
}
import
に依存するパッケージを追加します。
インポートしたパッケージはパッケージ名で参照できます。
matrixパッケージに定義したNew関数を呼び出すにはパッケージ名にドットをつけて呼び出します。
matrix.New(...)
関数の他に、型定義や変数も同様に参照できます
matrix.Matrix2D{}
matrix.PublicVar
ちなみに構造体を生成するときは中括弧を使用します。
ただし、今回のコードでは構造体のフィールドは a,b,c,d と小文字で定義されています。
これはプライベートを意味するのでパッケージ外から直接初期値をセットできません。
matrix.Matrix2D{}
ちなみに
インポート時に参照する名前を変更することもできます。
この時以下のように参照名を変更できます。
import (
myMatrix "github.com/yourname/example/matrix"
)
func main() {
myMatrix.New(1,3,3,4)
}
実行
go run main.go
GitHubに公開されているパッケージを使う
以下のように import 内に使用したいパッケージを指定します。
その後 go mod tidy
を実行するだけです。
注意 Go1.18を使用しています。古いGoではやり方が異なります。
// Snip...
import (
"golang.org/x/example/stringutil"
)
あとは同様にパッケージ名で参照します。
func main {
fmt.Println(stringutil.Reverse("olleH")) // Hello
}
まとめ
- パッケージの作成方法
- 構造体とそのメソッドの定義方法
- プライベート、パブリックについて
- パッケージの使用方法
あたりがわかったと思います。
最初にGoを触ると小文字がプライベートということによく引っ掛かります。
練習のうちは思考停止でアッパーキャメルケースを使用することをおすすめします。