Golangでバックエンドを実装する上での注意点

備忘録としてまとめる．何かの役に立てたら幸いです．
（2020/08/30更新：typeについて）
# Golang
## nilの意味
nullのこと．
SQLパッケージの場合は第二戻り値がerrかどうか返ってくるのでそれを使ってエラーハンドリングをする
[参考サイト](https://qiita.com/najeira/items/0bb0acdd7a71fc3f559b)


## 変数の定義
> 定義には明示的な定義(var)と暗黙的な定義(:=)が存在

[参考サイト](https://qiita.com/HiromuMasuda0228/items/65b9a593275f769f6b69)


## httpパッケージについて

`http.HandlerFunc`
~~関数の構造体．~~ -> `func(ResponseWriter, *Request)`の別名
（`type`の意味を正しく理解していませんでした．）

この定義によりhandlerの構造体を定義することなく関数を用意するだけでhandlerを書くことができる

```go
    type HandlerFunc func(ResponseWriter, *Request)
```
[参考サイト](https://qiita.com/nirasan/items/2160be0a1d1c7ccb5e65)


## typeについて

`type`をつけることで別名をつけることができる．これは既存の型や型リテラル（構造体，配列，ポインタ，関数，interfaceなど）が対象．`type`をつける利点の一つとして***メソッドの定義がある***
[typeと構造体について](https://qiita.com/tenntenn/items/45c568d43e950292bc31#type)

## for文について

golangではfor文で繰り返しの処理のすべてを実現
[参考サイト](https://qiita.com/megu_ma/items/ea9edd87d9c29f0d5e0f)


## エラーハンドリングについて

golangのエラー型`error`はinterface型なので独自のエラー型を定義するのが簡単．

```go
    type error interface {
      Error() string
    }
```
[参考サイト](https://qiita.com/minoritea/items/94feb33b61c5fdcc6105)
ただ，エラーの扱いについては様々な案がある．(後日追記予定)


## contextについて
> In Go servers, each incoming request is handled in its own goroutine. Request handlers often start additional goroutines to access backends such as databases and RPC services. The set of goroutines working on a request typically needs access to request-specific values such as the identity of the end user, authorization tokens, and the request's deadline. When a request is canceled or times out, all the goroutines working on that request should exit quickly so the system can reclaim any resources they are using.
> At Google, we developed a `context` package that makes it easy to pass request-scoped values, cancelation signals, and deadlines across API boundaries to all the goroutines involved in handling a request. 

[参考サイト](https://blog.golang.org/context)

私の解釈では，contextとはユーザ識別子, token, リクエスト期限などの情報をひとまとめにしたもの．これを使うことで様々なAPIを横断する際に処理が楽になると理解した．
[参考サイト](https://qiita.com/marnie_ms4/items/985d67c4c1b29e11fffc)
 

## logとfmtの違い

違いは，

- 表示形式（以下参考）
- 扱い
    - log: stderr
    - fmt: stdout

実行コード

```go
    func main() {
        fmt.Println("Hello fmt")
        log.Println("Hello log")
    }
```

出力

```
    Hello fmt   ← fmtパッケージ
    2017/05/01 09:00:34 Hello log    ← logパッケージ
```
[参考サイト](http://tsujitaku50.hatenablog.com/entry/2017/05/01/190250)


## goimportsの設定方法

通常golangではpackageのimport順序として以下のように記入する
これを自動で整形してくれるのがgoimports
また有名なエディタでは事前に設定すると自動フォーマットしてくれる．

```go
    import(
      // 標準package
    
      // github.comとか有名なpackage
      
      // 独自package
    )
```

[参考サイト](https://medium.com/@restartr/go-goimports-in-a-nutshell-d4dc2acb2b25)


## mapの扱い

[参考サイト](https://blog.y-yuki.net/entry/2017/04/26/000000)


## web frameworkについて

[参考サイト](https://qiita.com/yumin/items/5de33b068ead564ebcbf)


## sliceの戻り値について

sliceは参照型なので戻り値を工夫することができる
[参考サイト](https://medium.com/veltra-engineering/is-the-golang-slice-a-pointer-or-not-a-pointer-99433f2cea17)


## intの扱いについて

実行環境に依存しないように指定した方が安心
[参考サイト](https://blog.y-yuki.net/entry/2017/04/27/000000)


## 命名規則について

注意すべき点として，構造体のfiled名

- 頭文字小文字は同package内でのみ参照可能
- 頭文字大文字は同package外でも参照可能

[参考サイト](https://micnncim.com/post/2019/12/11/go-naming-conventions/)


# DB


## 操作について
- 昇順降順: `order by`
[参考サイト](https://www.sejuku.net/blog/72918)

- 個数指定: `limit`
- 取得範囲: `offset`
[参考サイト](https://www.dbonline.jp/sqlite/select/index10.html)

- 複数レコード取得
[参考サイト](https://qiita.com/tenntenn/items/dddb13c15643454a7c3b#複数レコードをselectしてみる)

- バルクインサート
[参考サイト](https://qiita.com/buntafujikawa/items/91283160b0a38956655e#バルクインサート)


## N+1問題
> 一覧に表示するデータを取得するために SELECT を 1 回実行（N レコード返される）
> → 
> 各データの関連データを取得するために SELECT を N 回実行
> → 
> 結果，データベースアクセス（SELECT）が合計 N+1 回も実行される

[参考サイト](https://www.techscore.com/blog/2012/12/25/railsライブラリ紹介-n1問題を検出する「bullet」/)

O/Rマッパー(ORM)（SQL文を書かずにDB操作ができる仕組み　ex. sqlalchemy）を使っていると遭遇しやすい問題だと思う．
→ 
解決策はあるので開発者の意識の問題だと感じた．
[参考サイト](https://www.slideshare.net/kwatch/how-topreventorm-troubles)