新しい言語で開発環境を作る時の目線ってこんな感じ(Go)

# 1. はじめに
開発環境を整える。初心者にとって一番高いハードルの一つです。でも、ある程度以上の経験を詰むと、言語を選ばずにスムーズに構築できるようになります。この記事は私の作業視点を整理して公開し、皆さんの苦手を克服する助けになればと記載しました。内容自体ではなく、「何をどうかんがえているのか」を見るための参考になったらうれしいです。

# 2. この記事の目的
私自身使ったことのない言語の開発環境の構築をなにをどう考えて、作っていくのかを整理していきます。あくまで一例として、作業のポイントなどをお伝えすることを目的としています。逆に「Go言語で効率よく開発する方法」などは全く含まれないのでご注意ください。

## 2-1 前提環境

導入OS先 Redhat Enterprise Linux 8

# 3. Go言語のコンパイル環境を作ってみよう

「開発環境」ってなんでしょうか。

1. プログラミング言語をコンパイルし実行できるようにする環境
1. コーディング、コンパイル、実行をシームレスに繋ぐための統合開発環境
1. システム全体のミニチュアを用意して、コーディング、コンパイル後の動作を確認するための環境

このいずれも「開発環境」とよばれうるものです。このでは狭義の開発環境として、1.を例にしていきます。つまり、この記事のゴールはGo言語で書かれたプログラムを実行可能な状態にコンパイルできる環境を作ること。です。

## 3.1 はじめての環境構築のながれ

私が新しいプログラミング言語を利用し始めるとき、こんな段取りをふみます。

![言語環境をととのえる.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/837176/08233a91-67b3-8523-080c-52f928265c7e.png)

### 公式ドキュメントの確認

最新バージョンの配布、インストールの方法など、「正しい」情報が詰まっている場所。それが「[公式サイト](https://go.dev/)」まずここを確認します。

観点は

1. インストール媒体の形式
2. インストール手順
3. 最新のバージョン

さて、軽く見てみましょう。まずはhttps://go.dev/ にブラウザでアクセスしましょう。

![WS000007.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/837176/cb16b9f6-5265-d10a-945d-8017f0cb3223.jpeg)

Windows/Mac/Linux and Moreとあります。More・・・なんか他にもいろいろ対応してるんですかね。。ちょっと一覧でみてみたいので、Moreの部分をクリックしてみます。

![WS000008.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/837176/7ccd7e92-1e50-1950-c6b1-5dbfe2bac628.jpeg)



|No.|対象OS|ファイル名|想定されるアーキテクチャ|バージョン|
|--|--|--|---|--|
|1|MS Windows 7 or later|go1.18.3.windows-amd64.msi|amd64|1.18.3|
|2|macOS 11 or later Apple 64-bit processor|go1.18.3.darwin-arm64.pkg|ARM|1.18.3|
|3|macOS 10.13 or later, Intel 64-bit processor|go1.18.3.darwin-amd64.pkg |amd64|1.18.3|
|4|Linux 2.6.23 or later, Intel 64-bit processor|go1.18.3.linux-amd64.tar.gz|amd64|1.18.3|
|5|Source|go1.18.3.src.tar.gz|-|1.18.3|

となっています。どうやら公開さているバージョンは1.18が最新のようですね。その他注目すべきなのはOSとファイル名です。

### 命名則

名前のきまりって、いろんなことを教えてくれますよね。たぶん、ここでは

```
go<バージョン><開発コード？>-<CPUアーキテクチャ>.<拡張子>
```

じゃないかと思います。darwinって多分このバージョンの名前≒開発コード何でしょうかね（想像）。面白いのはCPUアーキテクチャで、ほぼほぼx86系のAMD64で固められてるのに、「ARM」の文字が見えますね。これって、M1/M2マック用のプロセッサがARM系だからです。ここに「アーキテクチャ」を入れておくことで、M1用のバイナリを分けるときに、イイ感じに分岐できたと考えれば、この命名則を決めた人、M1 Mac登場時には「やったぜ」と思ったんじゃないかな。先に決めてれば。。。僕だったら小躍りしちゃいます。

### Windows

拡張子MSI、exeのファイルであれば問題なくインストールできると思っていいかと思います。ところで、WindowsはARM版もあるのに、amd64(=Intel/AMD)だけしかないのが、「そこのバイナリ作っても誰も使わないでしょ」って割り切りなんですかね。

### Mac

拡張子 pkgはMacのパッケージマネージャが使うやつですね。Macはそもそもファイルの種類を管理するのに拡張子を用いない哲学だったと思ってるのですが、まぁ、この方が分かりやすいよねと。AMDがMacOS10系からなのに、ARMがMac OS 11からなのは、面白いかな。つまり、Mac OS 10のM1 Macが存在しないってことですかね。時期的には多分これ。

### Linux

Linux向けの配布ってのは割といろいろバリエーションあるんで、理解するのが大変ですね。ざっくりとした分類だけ、ここでは取り扱います。

Linuxへの配布って大体以下のパタンです。

#### <1>ディストリビューションのパッケージとして配布する

debファイルもしくはrpmファイルで配布するケースです。debはDebian(Ubuntu)系、rpmはRedhat系で利用。依存するライブラリもパッケージマネージャ側で決定して入れてくれるので、ユーザの手間はだいぶ軽減されます。

#### <2>実行可能バイナリを、依存ライブラリ含めて全部アーカイブして配布する

依存するライブラリも全部入りで配布するパタンです。一番楽なんですが、OS側にすでにあるライブラリも二重で持つので、ディスク観点では不利。昔よりディスクが格段に安くなっているのが直接の原因か、選択されやすくなっています。

#### <3>ソースコードで配布する

パッケージ配布も全部要り配布も、対象のカーネルバージョンとか、命令セットとか前提を置かないと提供することはできません。たとえば、同じLinuxカーネルでもあまり使われていないARMプロセッサのためにわざわざ評価して、リリースするのは払う作業コスト（時間含む）のわりに、使ってくれる人がいない、とてもコスパの悪い作業になります。

そこで、「そういうニッチな人は、自分でコンパイルしてね。」とソースコードで提供するのです。

実は一昔前はこれが一番ポピュラーなリリース方法だったりもしました。ダウンロードしてmake config して・・・ってやってるとあれが足りない、これがたりないとすごい勢いで時間を溶かしてくれたものです。。。

Goでも、Source 配布していますね。Windows/Mac/Linux and More の「More」はこの部分のことでしょう。

## 3.2 パッケージの確認

では、各OSが提供しているパッケージマネージャではどうでしょうかちょっと確認してみましょう。

### Windows
Windowsのデフォルトパッケージマネージャはwingetです。最近導入されてすごく便利。さっそく私のWindows 11で確認してみましょう。

```cmd
> winget search go |findstr Programming
Go Programming Language                    GoLang.Go                                 1.18.3                     winget
```
ちょっとgoだけでは、多く出すぎるのでfindstrで結果を絞っています。優秀。超優秀。なんと、最新版のgo言語がwinget install で導入できることが確認されました。

### Redhat Enterprise Linux
RHELのパッケージマネージャはdnfですね。早速。確認確認

```bash
$ dnf install golang

================================================================================
 Package          Arch   Version         Repository                        Size
================================================================================
Installing:
 golang           x86_64 1.17.7-1.module+el8.6.0+14297+32a15e19
                                         rhel-8-for-x86_64-appstream-rpms 691 k
I

```
おしい。1.17ですね。別に最新版にこだわる必要もないんで、後の依存関係でぐだぐだ時間をとかすこと考えれば、dnf installを続けてもいいのですが、「公式から最新版を入れる」ってのが今回やりたいことなのでｗｗｗ。ここはいったん、中止します。

別に、古いから使っちゃいけないってわけじゃないです。サポート期間が残っていればあえて古いのを選ぶこともあります。今回は、「最新の1.18を使う」と決めて、進むので、いわば設計要素ですね。。

## 3.3 コンパイル環境作成しよう
### 3.3.1 公式手順の確認

再び、[公式サイト](https://go.dev/learn/)を確認してみましょう。

![WS000000.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/837176/efa7e29b-0a7e-63c0-85f7-c1f7582c8b61.jpeg)

view the install documentationにインストール手順がありそうです。

あ、ありましたね。「Linux」のタブを確認しましょう。

![WS000001.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/837176/ac802ed9-c49e-095b-e7f0-8bc58eb3e2d9.jpeg)

#### 3.3.1.1 手順の租借

1. Remove any previous Go installation

   ```
   $ rm -rf /usr/local/go && tar -C /usr/local -xzf go1.18.3.linux-amd64.tar.gz
   ```

    この手順はこんな風に分解されます。

    ```
    $ rm -rf /usr/local/go
    ```

    既にインストール済みのgoがあれば削除する。

    ```
    $ tar -C /usr/local -xzf go1.18.3.linux-amd64.tar.gz
    ```
    /usr/local配下に入手したファイルを解凍する。最初の削除ポイントを合わせて考えると /usr/local/goとしてディレクトリが展開されそうです。実際にインストールする場合にはこの部分をさらに分解してみましょう。

2. Add /usr/local/go/bin to the PATH environment variable.

あ、ディレクトリ構成は思った通りみたいですね。ユーザの設定情報として、$PATHに/usr/local/go/binを追加するわけです。

3. Verify that you've installed Go by opening a command prompt and typing the following command
   
   ```
   go version
   ```
インストールしたら、期待通りに動作するかを確認しないといけないです。とりあえず、goであれば、「コンパイルしてみる」ってのが手っ取り早いのですが、ソースコードが手元にないので、バージョン情報を表示しようということですね。

では、実際にやってみましょう。

##### (1) 媒体の取得

上述の[ダウンロードサイト](https://go.dev/dl/)からアーカイブを取得する。コマンドを使ってやりたいので、URLを取得しておく。

![WS000002.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/837176/c83e029d-de38-27d6-e7e1-bde9b9214d2d.jpeg)

``` bash
$cd /tmp
$wget https://go.dev/dl/go1.18.3.linux-amd64.tar.gz 

$ls go*
go1.18.3.linux-amd64.tar.gz
★ファイルが存在することを確認。
```
##### (2) 媒体の解凍

中身をよく観察したいので、2段階で解凍します。

``` bash
$cd /tmp
$sudo gunzip go1.18.3.linux-amd64.tar.gz 
$ls go*
go1.18.3.linux-amd64.tar
★.gzが無くなったことを確認する。
```

##### (3) 媒体の確認

では、どのような形で、リリース媒体が作成されているか確認しましょう。

``` bash 
    $cd /tmp
    $tar tvf go1.18.3.linux-amd64.tar|more

    …
    -rwxr-xr-x root/root  14537930 2022-06-01 09:52 go/bin/go
    …
```

やはり、go/binディレクトリが中に入っていますね。では早速解凍してみましょう

``` bash
$ cd /tmp
$ sudo tar xvf go1.18.3.linux-amd64.tar
$find go -type d|grep -v test|grep -v src|grep -v misc|grep -v pkg

go
go/api
go/bin
go/doc
go/lib
go/lib/time

```

```find go -type d```は指定のディレクトリ配下の全てのファイルの一覧を取得するコマンドfindを利用しています。find は```type d```とすることで、「ディレクトリ」だけを一覧します。この結果でもあまりにおおすぎるので```grep -v ``` に結果を渡して、実行には直接関係ない、src,test,misc,pkgを一覧から除外します。

別に/usr/local配下になくても、プログラムは動作しますので

```
./go/bin/go version
go version go1.18.3 linux/amd64

★バージョン情報が出力されることを確認
```

##### (4) 媒体の配置
さて、うまいこと動きさそうなことを確認したので、/usr/local配下に移動させましょう。

``` bash
$cd /tmp
$sudo mv go /usr/local/
$ls /usr/local/go/bin
go  gofmt
★goコマンドが配置されていることを確認する。
```

ではここでも簡単に動作確認しましょう。

```
$ /usr/local/go/bin/go version
go version go1.18.3 linux/amd64

```
もちろん最終的には ```go```というだけでgoコマンドが使えるようになりたいので、もうひと手間かけます。

##### (5) 環境設定

さて、プログラムは期待通りに配置された。あとはコマンドサーチパス＄PATH に/usr/local/go/binを設定する必要があります。

``` 
★sudoなしで一般ユーザで実行

cd

echo $PATH
/home/shupeluter/.local/bin:/home/shupeluter/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin
★/usr/local/go/binが入っていないことを確認します。

echo "PATH=\$PATH:/usr/local/go/bin" >> ~/.bashrc

source ~/.bashrc

echo $PATH
/home/shupeluter/.local/bin:/home/shupeluter/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/usr/local/go/bin

★/usr/local/go/binが入っていることを確認

go version
go version go1.18.3 linux/amd64

```

はい。期待通りインストールされたことを確認できました。


### 注意
なんどかgoコマンドを実行します。その途中、期待通りのコマンドが見つからないとRHELは以下のようなメッセージを出します。

```
bash: go: command not found...
Install package 'golang-bin' to provide command 'go'? [N/y] 
```

これは、「goってないけど、golang-bin パッケージ(ver 17)を入れるとそんなコマンドが入るけどいれていい？」って意味です。自分がやりたいことと合致しているならyと応えればいいですが、今回は我慢して進みましょう。