Goを1から学んでみた
この度Go言語を独学で学んで実務で使うことになりました。
チュートリアル、本、Udemyの講座で一通りGoの文法を学んでみて、1ヶ月経った後に実務で使うことになったのですが、1周目では気づかなかったけど2周目で腑に落ちて学べたことをメモします。
Go言語をやっている人には当たり前のことですが、他言語からスキルチェンジした人にとっては共感できることもあるかもしれません。
packageはディレクトリごとに管理する
Goではファイルの先頭にpackageをまず宣言するが、それは同じディレクトリにあるものは同じpackageを使うのが慣例。
同じpackageにある定数や関数はそのまま使える
同じlessonというpackageに属している2つのファイル間で定数numberを共有できる。
package lesson
const number int = 3
package lesson
const number2 int = number
ただし関数の中で宣言した場合、同じpackageや同じファイルであっても、関数の外で使うことはできない。
その場合スコープは関数の中のみとなる。
異なるpackageの変数や関数を使う場合はimportしてpackage名.関数名で使う
import (
"***/read"
)
read.create()
構造体の宣言は{}の中にフィールド名+スペース+型で、実体のデータは{}の中にフィールド名: 値を入れる
type struct type {
name string
age int
}
pome := dog {
name: "pochi",
age: 9,
}
構造体の宣言では間はスペース、羅列する際はカンマなしで次の行。
構造体の実態は:で区切ってカンマで羅列する。フィールド名は省略可能。
一列に列記する場合は最後のカンマは不要だが、一列に一フィールドの場合最後にもカンマが必要。
当たり前のことだが、最初は混乱するので記載。
構造体のメソッドでもレシーバーや引数で変数名.フィールド名orメソッド名で構造体の持つフィールドやメソッドにを使える
func (d dog) describe(d2 dog) string {
return d.name + d2.dog
}
func (d dog) get() {
d.describe()
他のpackageを使う時と同じように.で使用するので混乱することがある。
構造体初期化のパターンの一例
type Dog struct{
name string
}
func New(name string) *Dog {
return &Dog{name}
}
dog := New("pochi")
引数で取得した値をポインタ型の構造体に入れてreturnする。
構造体のmap
map[string]struct {
name string
}{
"テスト": {
name: "犬"
}
}
//空でも作成可能
map[string]string{}
テストケースを作るときによく使う形。キーの方と構造体の型を指定してキー:構造体を続けて記述する。
中身のフィールドで必要ないものは記述しなくても大丈夫。
型を統一したいときにインターフェースを使う
interfaceを使って異なる構造体を同じインターフェースで抽象化できる。
interfaceにはそれに属するためには持たなければならないメソッドを記述する。
そのメソッド名と引数と戻り値が同じメソッドを持つ構造体はそのインターフェースで抽象化される。
テスト作成でmockを使いたい時にinterfaceからmockを作成して、interfaceの持つメソッドの戻り値を仮の値にすることができる。まだ未定の値やそのメソッドから叩くAPIが未完成の場合、わざとエラーを起こさせてエラー系のテストをするときなどにmockを利用することがある。
interfaceをフィールドにもつ構造体をNewで生成
type InterfaceLesson interface {
Describe() string
}
func New(lesson lesson.InterfaceLesson) *Dog {
return &Dog{
lesson: lesson,
}
}
Describe関数の戻り値を仮に設定してmockを作ることができる。
mock.Expect().Describe().Return("仮の戻り値")
New(mock)
変数宣言
// 明示的宣言
var a int = 6
// 初期値デフォルト stringは空文字 intは0
var b string
// 暗黙的宣言
c := 8
//代入
c = 4
// 配列の宣言
array := [3]int{1,2,3}
var array2 [3]string = [3]string{abc}
関数の外で宣言する場合暗黙的宣言の変数は使用できない。
配列の場合値を入れる際にも型が必要。
配列の中身は他の言語だと[]で入れられるが、Goだと{}で入れることに注意。
定数宣言
const A = "abc"
const B int = 7
定数は型宣言がなくても宣言できる。
配列、スライス、mapは宣言できない。
基本的には関数の外で宣言する。packageの外で使いたい場合は名前を大文字にする。
print関数
fmt.Print("a")
fmt.Fprint(w, "a")
APIレスポンスに書き込みたい場合はresponse writerに書き込み。
testなどでデバックしたい場合はPrintで書く。
go testコマンドで-vを使うと見ることができる。
テスト関連
r := httptest.NewRequest(http.MethodGet, "http://localhost?"+param.Encode(), nil)
httptestでは第二引数のURLはhostだけで良くてパスはなしでparamをつければ大丈夫。
その後に対象の関数を呼び出せばいい。