環境設定
-
Go言語仕様
https://golang.org/ref/spec -
goのインストール
https://golang.org/ -
go getでパッケージを取れるか
https://pkg.go.dev/
go get xxxx -
Goland
有料のIDE -
VSCode
cmd + j でVSCodeのパネル開く
go run xxxx.go で実行
go build xxxx.go でバイナリファイルが残る -
delve デバッガ
go get github.com/go-delve/delve/cmd/dlv
launch.jsonを作成 -> vscodeのrunタブにボタンが有る
基本
- main.goから始まる
- init() 関数は強制的に最初に実行される
- 使わない変数を書くとコンパイルできない
- 先頭は大文字でパブリック、小文字だとプライベートになる
- fmt.Println()で出力
import
標準パッケージ一覧
https://golang.org/pkg/
パッケージはimportして使う
パッケージとはコードの集まり。ライブラリもほぼ同じ意味。クラスはない。
ディレクトリ名がpackage名となる。その中にgoファイルを配置。
app
L main.go
L package1
L file1.go
L file2.go
L package2
変数
var i int = 3
float64, string, bool
var を () でくくればvarを毎回先頭に付ける必要はない
初期値を代入しなかった場合デフォルト値となる。0、空文字、falseなど
fmt.Printf("%T\n", xi)
short variable declaration
xi := 1
xs := "ccc"
代入により自動で型が決まる
関数内でしか使えない
const
書き換えられない
型がない(untype)(実行するまで解釈されない)
通常はグローバルに書く
通常は先頭は大文字
数値
言語仕様
https://golang.org/ref/spec#Numeric_types
i++ 対応
文字列
インデックス指定でアスキーコード取得、stringで文字に変換
string("Hello"[0])
文字の置き換え
var s string = "Namaste"
s = strings.Replace(s, "N", "Z", -1)
strings.Contains(s, "mas")
バッククオートでヒアドキュメント ``
論理値
変わったところはない
&& || !
型変換
int float64
文字 -> 数字はpythonみたいにstringではできない
i, _ := strconv.Atoiで変換
戻り値をアンダースコア(_)で受け取れば、未使用でもコンパイルできる
配列
型部分で宣言したサイズは変更できません
var b [2]int = [2]int{30, 40}
スライス
サイズ変更できる配列
var b []int = []int{30, 40}
b = append(b, 50) で追加
var n []int 初期化しないとnilになる
n := make([]int, 0) だと中身は空だがメモリ上に存在する
map
m := map[string]int{"apple": 100, "banana": 300}
新しいキーに代入すると追加される
var m map[string]int 初期化しないとnil mapになり、追加できない
m := make(map[string]int) はnilじゃない
a, ok := m["grape"]
keyが存在しないと0を返し、2つ目の返り値にfalseが返る
バイト
b := []byte{72,73}
stringで文字列にキャストできる
c := []byte("HI")
文字列を渡すとアスキーコードに変換される
アスキーコード変換表
https://www.ascii-code.com/
関数
引数の型が同じ場合はまとめられる
返り値が複数の場合は()でくくる
func add2(x, y int) (int, int) {
return x + y, x - y
}
名前付きの戻り値 Named Return Values
func calc(price, item int) (result int) {
result = price * item
}
返り値として宣言した名前を変数として扱えるので、returnを書く必要なし
返り値が多くなってわかりにくい時など
Inner Function
関数内で変数に関数を代入して使う
f := func()
名前無し関数も作れる
func(x int) {
}()
クロージャー closure
関数を返す関数
func increment() func() int {
関数を戻す前に投入したパラメータを、戻した関数の処理に引き継ぐ事ができる
func circle(pi float64) func(radius float64) float64 {
return func(radius float64) float64 {
return pi * radius * radius
}
}
可変長引数 Variadic Function Parameter
任意の個数の引数を受け取れる
func foo(params ...int) {
関数の中ではスライスで受け取れる
スライスを可変長引数の関数に渡すには
// スライスが展開される
foo(s...)
コードスタイル
イコールの位置をそろえるのがgoの慣習
列挙する場合は演算子は詰めて書く
var a = 100
var bbbb = 200
var cc = 300
fmt.Println(1+1, 2*2)
##ステートメント
if
()はなくて良い
;で一文でかける
// if / else if / else
if result == "ok" {
for
continue
break
//初期化とインクリメントを省略できる ;も省略できる
for sum < 10 {
}
for { } だけだと無限ループできる
range
リストやマップをかんたんに表示できる
for i, v := range list {
インデックスを使わない場合は _ で置き換える
マップのバリューのみ使わない場合は書かない
マップのキーのみ使わない場合は _ で置き換える
switch
switchの判定のみ使うのなら、;の前で取得して一文でかける
変数を書かなくても分岐に使える
switch {}
defer
前につけることで関数が終わったあとに実行する指示
close処理忘れ防止など
func defaTest() {
defer fmt.Println("defer") // 関数が終わったら実行されます
fmt.Println("end")
}
deferはスタッキングされるので、複数あると最後から表示される
log
go logging package
log.Println()
log.Fatalln() // Fatalはそこでプログラムが終了する
log.SetOutput //設定
エラー
goは戻り値のerrを使って処理する(トライキャッチじゃなく)
:= はどれか一つを初期化してたらエラーにならないが一つもなければアウト
count, err := file.Read(data)
panic、recover
deferでrecover()してpanic()が起きても正常終了させる
recoverはpanicの前に書く
基本panicをあえて書くのではなく、エラーハンドリングをするべき
ポインタ
ポインタ
var p *int = &n //intのポインタ型、アドレスを格納
p //アドレス
*p //ポインタが指す値
new make
指定の型のメモリ確保する
var p *int = new(int)
*p は0になる
スライスやマップはmakeでメモリ確保(ポインタを返さない)
struct 構造体
先頭は大文字でパブリック、小文字だとプライベートになる
type Vertex struct {
X int
Y int
S string
}
v := Vertex{X: 1, Y: 2}
初期化しなければデフォルトが入る
名前を指定しなければ順番どおりはいる
アドレスを取る場合、newよりも&を先頭につける事が多い
(マップやスライスなどはmakeを使うほうが多い)
structの場合は、参照渡しでも*つけずに値にアクセスできる!!
struct
メソッド
定義済みstructに関連付けてドットで呼び出せる関数(値レシーバ)
func (v Vertex) Area() int {
structを参照渡しして、メソッド内で中身を書き換えるもの(ポインタレシーバ)
func (v *Vertex) Scale(i int) {
コンストラクタ
structをプライベートにすると他のパッケージからアクセスできないので
Newメソッドで初期化する
func New(x, y int) *Vertex {
return &Vertex{x, y}
}
packageName.Newすることでstructを返す
embeded
structの中にstructを定義すると、クラス継承みたいな感じで拡張できる
type Vertex3D struct {
Vertex //名前を書くだけ
z int
}
func New(x, y, z int) *Vertex3D {
return &Vertex3D{Vertex{x, y}, z}
}
non-struct
structではないカスタム型もメソッドをつけられる
type MyInt int
func (i MyInt) Double() int {
interface
メソッド名だけ書かれている型
structがメソッドを実装してないとエラーになる
type Human interface {
Say()
}
使うにはstructを作るときに変数の後ろにつける
var mike Human = Person{"Mike"}
引数をinterfaceで宣言して、メソッドを実装済みのstructのみ受け付けるようにできる(ダックタイピング)
タイプアサーション
引数の型を interface{} にすれば何でも渡せる
その場合、i.(int) などで型を変換することをタイプアサーションという
インターフェースでない通常の型の変換(タイプコンバージョン、キャスト)とは違う
switch type文で複数の型に対応
Stringer
string()メソッドを実装するとそれが標準出力になる
func (p Person2) String() string {
カスタムエラー
自分なりのエラーを出したい場合はString()同様、Error()を実装すればよい
func (e *UserNotFound) Error() string {
Error()はポインタ型推奨
エラーを比較するときはポインタで比較しないと同じエラーになっちゃう
まとめ
C言語みたいだと感じた