Go言語で初心者がハマりそうなところ

# はじめに

Go言語を勉強する際、初学者がハマりそうなところ（というよりも私がハマった部分）を列挙しました。

1. ソースコードを置く場所
2. パッケージ外部から呼び出せる関数・変数の設定
3. 自作ライブラリをimportする方法
4. enhanced for loop で要素ではなく添え字が出力される

以下、備忘録も兼ねてそれぞれどういうお話かを述べます。

# 前提条件

## Linuxの作法で説明

環境変数などについては、Linuxの作法（例：環境変数やパスのセパレーター）を理解している前提で説明します。
特に説明はしません。

## 環境

以下の環境で作業しています。実環境はWindows/Cygwinですが、Linux前提の作法で話していきます。

|項目|環境|
|:--:|:--:|
|OS|Windows 10 |
|シェル|コマンドプロンプト/Bash(Cygwin 3.0.7上)|
|エディター|Atom editor|
|Go| ver 1.12|
|Cコンパイラ| gcc x86_64-w64-mingw32 8.3.0|

### 記事内のソースコードを動作確認した環境

[The Go Playground](https://play.golang.org/)を使用しました。


## GitHubアカウントを持っている

すぐ次に出てきますが、GitHubアカウントを持っている前提で話します。
ちゃんとバージョン管理をするためにも、GitHubを活用しましょう。


# 1. ソースコードを置く場所 

階層構造を持たせ、パッケージを分ける時点で必ず通る関門です。

## 結論

置く場所は`$GOPATH/src/github.com/{GitHubアカウント名}/{ライブラリ名}`です。

例えば、GitHubアカウント`me`でライブラリ`my-first-go-app`を作成した場合は、
`$GOPATH/src/github.com/me/my-first-go-app`です。


## 理由

実際に私が使わせていただいた以下のライブラリを例に、説明します。
[あなたのWebサービスでLDAPユーザ認証を実現するgo-ldapc (Qiita)](https://qiita.com/sonatard/items/0497a447e789b12de251)


GitHub上のレポジトリは[https://github.com/sonatard/go-ldapc](https://github.com/sonatard/go-ldapc)です。

Go言語におけるライブラリインストールは `go get [パッケージ]`コマンドで行いますが、実行すると`$GOPATH/src/[パッケージ]`に保存されます。

つまり、go-ldapcをインストールするために

```bash
go get github.com/sona-tar/ldapc
```

を実行すると、`$GOPATH/src/github.com/sona-tar/ldapc`に保存されます。

このディレクトリにあるライブラリをimportするには、

```go
import "github.com/sona-tar/ldapc"
```

とGo言語のソースコードに書きます。


**自分が作成したライブラリを第三者に公開する場合、必ずこの作法で作成しましょう。**
~~「ま、どこに作っても一緒やろ！」と横着すると、自分が過去作ったライブラリのインポートすら碌にできなくなります。~~




# 2. パッケージ外部から呼び出せる関数・変数の設定

関数・グローバル変数を別パッケージから呼び出すには、頭文字を**大文字**にする必要があります。

```go
package hoge

import "fmt"

var (
  x int = 0  //パッケージ hoge でのみ参照可能
  Y int = 0 //他のパッケージからも参照可能
)

// パッケージ hoge でのみ参照可能
func f1() {
  fmt.Println("F1!!")
}

 //他のパッケージからも参照可能
func F2() {
  fmt.Println("F2!!")
}

```

```go
package main

import (
  "fmt"
  "github.com/user/repository/hoge"
)

func main() {
  hoge.f1() // コンパイルエラー
  hoge.F2() // 動く

  fmt.Println( hoge.x )  // コンパイルエラー
  fmt.Println( hoge.Y  ) // 動く
}
```

この例で出てくる`fmt`パッケージ中の関数`Println`も頭文字が大文字です。

# 3. 自作ライブラリをimportする方法

先に述べた[1. ソースコードの置き場所](#1-ソースコードを置く場所 )と連動しますが、GitHubアカウント`me`でライブラリ`my-first-go-app`を作成した場合を説明します。


# ライブラリ全体をimport

通常の作法で、以下のようにimportします。

```go
import "github.com/me/my-first-go-app"
```

## 特定のパッケージのみimport

以下のようなディレクトリ階層構造を想定します。

```bash
my-first-go-app
├── hoge
│   └── hoge.go
├── huga
│   └── huga.go
└── main.go
```

`main.go`からパッケージ`hoge`をimportしたければ、`main.go`中で

```go
import "github.com/me/my-first-go-app/hoge"
```
と書きます。

パッケージを参照する際の名前を変更することも可能です。

```go
import hogehoge "github.com/me/my-first-go-app/hoge"
```

とすれば、

```go
hogehoge.Y
```
のように`hogehoge`という名前で参照することができます。


# 4. enhanced for loop で要素ではなく添え字が出力される

```go
items := []string{"A", "B", "C"}

for item := range items {
  fmt.Println(item)
}
```
と書くと、

```
0
1
2
```
を出力します。

## 結論

以下のように書きます

```go
items := []string{"A", "B", "C"}

// 添え字が不要な場合
for _,item := range items {
  fmt.Println(item)
}

// 添え字も必要な場合
for index,item := range items {
  fmt.Printf("items[%d] = %s\n", index, item)
}
```

## 理由

range は以下の二つの返り値を持ちます。

- 第一返り値：添え字
- 第二返り値：配列の要素


# 参考元
[Goのfor rangeで思った値が取れなかった話 (Qiita)](https://qiita.com/modal_soul/items/e49480e5692597fda975)