【Part1】Go言語(golang)の基本とTips

環境

  • Windows 10
  • golang1.18
  • VSCode
  • Docker
masayan
masayan

以下のドキュメントは一読されることをおすすめします。

https://go.dev/doc/effective_go

本シリーズの記事で説明する内容

  1. きほんのき
  2. ファイル、クラス等の命名規則や慣習
  3. 環境構築
  4. モジュールのimport
  5. 変数定義と代入
  6. ポインタ
  7. 配列・スライス
  8. マップ
  9. 繰り返し
  10. 条件分岐
  11. 関数
  12. ジェネリクス
  13. クラスの作り方(正確にはクラスではない)
  14. インターフェース
  15. 単体テスト
  16. フォーマット
  17. その他Tips
masayan
masayan

本記事(part1)では、上記の1~4について説明します

きほんのき

  • Go言語はPHPなどのインタプリタ言語とは違い、コンパイル言語
  • プログラムの実行方法
    • 主にコンパイル方式をとるが、インタプリタ方式で実行することも可能
      • インタプリタ方式
        • go run main.go
      • コンパイル方式
        • go build main.go でコンパイルして、./main でバイナリを実行
masayan
masayan

Go言語はオブジェクト指向言語か?という論争については

クラスが用意されていない等の理由により、オブジェクト指向言語ではない、という意見もあれば、そうでないという意見もあるようです。

ファイル、クラス等の命名規則や慣習

全般

  • 複数単語から成る名前をつけるときはアンダースコアを使用せず、MixedCapsまたはmixedCapsのように単語の先頭だけ大文字を用いる
var customerName string = “tanaka”

ファイル名

  • csv_reader.goのように、スネークケース(すべて小文字で、複数の単語をアンダースコアで

構造体(struct)

  • アッパーキャメルケース(先頭大文字から始まる)かローワーキャメルケース(先頭小文字から始まる)で
  • なお、Goにはクラスはないので、クラスが必要な場合は構造体で実装する必要がある
type Recipe struct {
    id   int
    name string
}

関数

  • キャメルケースを使用。エクスポートされる関数は大文字で始める必要がある点だけ注意
  • アクセス修飾子はなく、先頭が大文字ならpublic、小文字ならprivateになる
package util

// スライスの要素数を返す関数です
func Count[T any](array []T) int {
    return len(array)
}

定数

  • constで宣言する
  • ドキュメントでは特に触れられてないので、特に明確なルール等はなさそう

パッケージ名

  • すべて小文字1語の名前を付ける。アンダースコアやmixedCapsは不要
  • シンプルに付けること。重複しそうなときは別名importを使用
  • package util package timeなど

ゲッターセッター(メソッド)

  • 例えば、nameというフィールドなら、
    • ゲッター: Name()
    • セッター: SetName()
  • 前述の通り、エクスポートされるメソッドは大文字で始める必要がある点だけ注意。

インターフェース名

  • 1つしかメソッドがないインターフェース
    • 慣習によりメソッド名に加えて-er接尾辞とする
package interfaces

type CsvReader interface {
    ReadAll() (record [][]string, err error)
}
  • 2つ以上メソッドがあるインターフェース
    • 特にルールはなし

セミコロン

  • 基本不要

スコープ

  • local
    • if, for等のブロック内で宣言されている
  • package
    • 先頭小文字でif,forなどのブロック以外(ブロックの外)で宣言されている
  • global
    • 先頭大文字でエクスポートされている

環境構築

  • 環境ごとにymlファイル、Dockerfileをいい感じに分ける必要がある気配

開発環境

  • golangが動くimageを使用したDockerでコンテナを立て、fresh等のライブラリを使用してホットリロードができるように
    • fresh
      • ソースコードに変更があると、自動ビルドしてくれるライブラリ
      • 実行する際は、プロジェクトのルートディレクトリでfreshを打つだけ

本番環境

  • Dockerfileのマルチステージビルドでコンパイル環境と実行環境を分ける
    • マルチステージビルドとは、1つのDockerfileでFROMを複数使用してbuildを行うこと
  • 本番ではビルドしたバイナリだけを使用することで、最終的な出力イメージを小さくし、パフォーマンス向上およびセキュリティホールの対策にもなる

Dockerfile

# 本番用の中間ステージ
FROM golang:1.18.2-alpine3.15 as builder

RUN apk update \
&& apk add --no-cache git

COPY sample-go-app /sample-go-app
WORKDIR /sample-go-app
RUN go mod download
RUN go build -o /main ./cmd/main.go

# 本番用ステージ
FROM alpine:3.15 as prod
COPY --from=builder /main .
ENV PORT=${PORT}
CMD ["./main"]

Dockerfile.dev

# 開発環境用ホットリロード

FROM golang:1.18as dev
WORKDIR /sample-go-app
COPY ./sample-go-app/go.mod ./sample-go-app/go.sum ./
RUN go install github.com/pilu/fresh@latest

モジュールのimport

  • 多言語でも、自作クラスのモジュールやクラスのimportがしばしばハマり要素ではあるが、Goでは、GOPATHモードとGoModulesモードがあり、現在は後者が推奨

GOPATHモード

  • 標準pkg以外を全部 $GOPATH以下のディレクトリで管理する仕様
  • プロジェクトも $GOPATH/src配下に作成する必要があり、この制約が開発環境の構築にネックとなっていた

GoModulesモード

  • 現状のデファクトスタンダード
  • go.modファイルを使用する
  • GoModulesは、Go1.11から導入され始めたGoの新しいバージョン管理システム
  • 標準pkg以外の全てのパッケージをモジュールとして扱い、モジュールの管理やビルドが任意のディレクトリで可能に
  • import手順は以下の通り
    • go mod init <モジュール名> を実行
    • ディレクトリにgo.modというファイルが作成される
    • 呼び出し側のファイルで、import <モジュール名>/<パッケージ名> で読み込む
  • go.modサンプル
    modulemymodule
    
    go1.18
    
    require (
       github.com/davecgh/go-spewv1.1.0// indirect
       github.com/golang/protobufv1.4.2// indirect
        ・・・割愛・・・
    
    )
  • 自作モジュールは、go.modのmodule名+go.modがあるディレクトリからの相対パスを指定することでimport可能
  • 例えば、プロジェクトのルートにgo.modがあり、一つ下の改装にinterfacesというディレクトリがあり、その中のモジュール(パッケージ名:interfaces)をimportしたい場合は以下のようになる

    package main
    import (
        "mymodule/interfaces"
    )
    
    
    func main() {
      file := "sample.csv"
      // interfaceに代入
      var csv_reader interfaces.CsvReader = classes.NewCsvReaderImpl(file)
      records, _ := csv_reader.ReadAll()
      ・・・
    }

外部ライブラリのインストール

go install <package>@<version>でインストール可能です。インストールすると、go.modファイルに追記されます

※go get <package>でも可能

以上です。次回partでは5.~8.までの説明を行いたいと思います

    Go学習におすすめの書籍

    タイトルとURLをコピーしました