Go言語初めの一歩踏んでみましたというお話。
はじめに
こんにちは, 42tokyo Advent Calendar 2021の22日目を担当する, 在校生のrakiyamaです。
この記事では, Go言語の学習で私が躓いたことについてまとめました.
環境 : Mac
現在のGoの最新バージョン : 1.17
Goのインストールはbrew install go
で行いました(その他インストール方法参考).
本記事で載せている参考リンクは英語の記事もありますが(気合い(DeepL)で読むと意外と読めます),
探せば日本語版もあるかもしれません.
基本用語
ダウンロード
意味: 対象物を持ってくる.
例: 利用したいプログラムのソースコードを自分のパソコンにコピーする.インストール
意味: 対象物を実行できるようにする(この過程でダウンロードやコンパイルを含むこともある?, 目的はあくまで実行できるようにすること).
例: バイナリファイル(実行形式のプログラム)を適切なディレクトリ(/binなど)に配置する.バージョン
Goの話でバージョンという言葉が出たら以下を指すことが多いみたいです.- Go言語自体のバージョン
- レポジトリやモジュールのバージョン
※レポジトリとモジュールがよく分からなければひとまずレポジトリは忘れて, モジュールを"プログラムの一つのまとまり"として先に進みましょう.
仕様に変更が加わってGo1.10からGo1.11になりましたよ〜っていう感じで更新を識別するための表記のことですね.
GOPATH
パッケージ
GOPATHとモジュール
Go言語ではファイルの管理方法が定められていて, 以下の二つがあります.
- GOPATHなるものを基準にする方法(GO1.10まで)
- モジュールなるものを基準にする方法(GO1.11から徐々に標準となった)
Go言語で開発する際のルールと捉えています.
私はこの管理方法がバージョンによって変わることを知らなかったので, 学習を進める中でめちゃんこ混乱しました.
仮にここではGOPATHに従う方法をGOPATHモード, モジュールに従う方法をモジュールモード(公式ではmodule-aware modeとか書いてあります) として話をします.
GOPATHモード
GOPATHモードでは, 以下のようなディレクトリ構造をGOPATH配下に作成し, ファイルを管理します.
このディレクトリをルートディレクトリとして作業を進めるため, ワークスペースとも呼ぶみたいです.
GOPATH/ bin/ バイナリファイル pkg/ パッケージのオブジェクトファイル src/ ソースコード (全てのソースコードはここに)
開発を進める際のルートディレクトリは常にGOPATHであり, ソースコードはsrcディレクトリの中で管理します.
つまりGOPATHの中でのみ開発を進めるという特徴があります.
「ワークスペースのsrc内にファイルを作成しましょう」みたいな話が参考サイト等で出てきたら,
GOPATHモードが前提の話だと思います.
実際どのようにプログラムを作成するのかは以下リンクが分かりやすいです.
go.dev
モジュールモード
ここで新たにモジュールという概念が出てきます.
- モジュール
- 1つ以上のパッケージをまとめたもの.
実体は, パッケージ + バージョン管理情報.- バージョン管理とは
依存関係にあるモジュールのバージョンや
使用しているGoのバージョンの情報を
(ファイルに明示的に記述しておくなどして)管理しておくこと.
- バージョン管理とは
- 例として, 先ほどのパッケージをモジュールでまとめたイメージを載せます.
ポイントはバージョン管理によりモジュールの依存関係がまとめられていることです. 仮に作ったstringmanipモジュールのバージョンを0.0.0とすると,
stringmanipモジュール0.0.0のビルドの再現性がバージョン管理によって確保されています.
GOPATHモードではこのバージョン管理の仕組みが標準で用意されていなく苦労してたみたいですが, どのように対処していたのか詳しくはわかりません.
- 1つ以上のパッケージをまとめたもの.
モジュールモードでは, ファイルをパッケージにまとめ,
さらにパッケージをモジュールとしてまとめてプログラムを作成します.
ルートディレクトリにgo.modというバージョン管理ファイルを用意すれば,
そのディレクトリ自体はどこに位置しても大丈夫です(goコマンドが使えるところならおそらく).
要はGOPATHモードに比べて,
バージョン管理の仕組みが用意され, 開発に関しても任意のディレクトリで行えるようになったので,
便利になったということです.
ちなみにGOPATHは引き続きインストール先などで利用されています.
参考リンク GOPATH に(可能な限り)依存しない Go 開発環境(Go 1.15 版)
モジュールのディレクトリ構造
ここでは先ほどのモジュールのイメージを元に実際のディレクトリ構造を載せます.
とてもざっくり説明なので, 詳しくは以下のリンクを参考にしてください.
go.dev
自作パッケージを用意して, main.go内で使う
↓ディレクトリ構造
. ├── convertstrings //自作パッケージconvertstringsを含んだconvertstringsディレクトリ │ ├── lower.go │ └── upper.go └── main.go
↓バージョン管理ファイル(go.mod)作成
//ターミナル $> go mod init stringmanip(モジュール名) $> tree . ├── convertstrings │ ├── lower.go │ └── upper.go ├── go.mod └── main.go
↓自作パッケージ(convertstrings)のimport
//main.go package main import "stringmanip/convertstrings" //使いたいパッケージのディレクトリパスを指定 //go.modのある場所をモジュール(stringmanip)全体のルートディレクトリとして考える func main () { convertstrings.Upper("string") }
外部パッケージも使う
↓外部パッケージのimport
//main.go package main import "stringmanip/convertstrings" import "github.com/example/language/translate" //リモートレポジトリから使いたいパッケージまでのディレクトリパス指定 func main () { convertstrings.Upper("string") translate.Spanish("string") }
↓go.modの編集, go.modのあるディレクトリで以下を実行
//ターミナル $> go mod tidy
main.go内でパッケージ名とそのディレクトリ名が同じで分かりにくですが,
importパスで指定しているのはディレクトリで
convertstrings.Upper()
のように使用する際に先頭に付けているのはパッケージ名です.
モード操作
現在のモードの確認
$> go env | grep GO111MODULE GO111MODULE="on" #常にモジュールモード GO111MODULE="off" #常にGOPATHモード GO111MODULE="auto" #go.modファイル(バージョン管理情報をまとめたファイル)がカレントor親ディレクトリにある時のみモジュールモード
モードの変更
$> go env -w GO111MODULE=auto # autoに変更
Goについて参考になった情報
困ったらこれ
Documentation - The Go Programming Language
一つ一つのトピックがシンプルにまとめられていて非常に分かりやすいです.コードの書き方
- Go の最初の手順 - Learn | Microsoft Docs
私はこちらを参考にコードの書き方を学びました.
日本語で基本的文法などはわかりやすいですが,
GOPATHとモジュールが混ざっているのでその辺ややこしいです. - A Tour of Go
- Hello, World - Learn Go with tests
- Go の最初の手順 - Learn | Microsoft Docs
その他
Go のモジュール管理【バージョン 1.17 改訂版】
Go言語でハマったことメモ(ポインターのアロー演算子がない) - 新しいことにはウェルカム
golangではスタックとヒープを気にする必要が無い
まとめ
ファイルやディレクトリ構成はHow to Write Go Code - The Go Programming Languageを参考にモジュールで考えれば良いんだなーということが伝われば幸いです!!
どこか間違った点があればご指摘頂けると嬉しいです。
明日はrsudoさんがイケイケ開発環境構築について記事を書いてくれる予定です!お楽しみに!