Closed12

Goをやっていき。

スースー

Go をやっていく

公式のチュートリアル(Tour of Go)

https://go-tour-jp.appspot.com/list

公式ドキュメント

https://golang.org/doc/

標準パッケージ一覧

https://golang.org/pkg/

注意事項

  1. 基本的な文法をここでカバー
  2. 詳細についてはもっと別なところでやる必要がある

やることリスト

  1. 公式チュートリアルやる
  2. 認証なし定数を返すだけのGETとPOSTAPIとか試しにかく
  3. Gormを使ってDBから値を引き出して返すようにする
  4. ↑でCRUDを全て制覇する
  5. APIを認証付きにしてみる→よくあるやり方をキャッチアップする(JWTくらい?)
  6. GoでAPIテストを書く→綺麗な書き方も見る。よく使われるライブラリがあればそれを使う
  7. Goで単体テスト書く→綺麗な書き方も見る。よく使われるライブラリがあればそれを使う
  8. 本番運用を想定して、ロギング周りを調べて書く
  9. 外部APIとの通信を想定した処理を書く
  10. ↑と自前の中でException周りの想定したものを書く
  11. キャッシュ周りをかく
  12. RedisなどのNoSQLとの連携を書く
  13. Goのlinterについて調べてカスタマイズする

Goでの落とし穴についてのリンク集

https://future-architect.github.io/articles/20190713/

https://medium.com/eureka-engineering/golang-の-const-と-var-のコンパイル時解釈-b313a11ce2c3

https://blog.golang.org/defer-panic-and-recover
→defer statementについての詳細

ディレクトリ構成について

https://github.com/golang-standards/project-layout

https://github.com/golang-standards/project-layout/pull/88

スースー

Goを触ってみた時の感想

  1. Go で「()」は書かない→PHPとかなり異なるw。ifとかも書かないので、書き味注意
  2. constの使い方気をつけないとPHPと異なるのでコンパイルエラーになるよ
  3. タイプヒンティングは後ろ付。
  4. deferによる関数の実行を遅らせるというパターンの使い所がわからん。(PHPでは使いにくい概念かも)

補足

https://www.php.net/manual/ja/swoole-server.defer.php
一応PHPもdeferはあるらしいw

スースー

変数の影響範囲


Switchの厳密性検証

switch.go
package main

import (
	"fmt"
)

func main() {
	fmt.Print("Go runs on ")
	switch os := 1; os {
	case "1":
		fmt.Println("OS X.")
	case 1:
		fmt.Println("Linux.")
	default:
		// freebsd, openbsd,
		// plan9, windows...
		fmt.Printf("%s.\n", os)
	}
}

これだと、最初の次のエラーが出る。
厳密でとても良い。

./prog.go:10:2: cannot use "1" (type untyped string) as type int

長くなりがちなif-elseを端的に表現

switch-with-no-condition.go
package main

import (
	"fmt"
	"time"
)

func main() {
	t := time.Now()
	switch {
	case t.Hour() < 12:
		fmt.Println("Good morning!")
	case t.Hour() < 17:
		fmt.Println("Good afternoon.")
	default:
		fmt.Println("Good evening.")
	}
}

スースー

defer

deferの関数は、呼び出しもとmainの実行が終わるまで遅延させられる。

package main

import "fmt"

func main() {
	defer fmt.Println("world")

	fmt.Println("hello")
}

pointer

package main

import "fmt"

func main() {
	i, j := 42, 2701

	p := &i         // point to i
	fmt.Println(*p) // read i through the pointer
	*p = 21         // set i through the pointer
	fmt.Println(i)  // see the new value of i

	p = &j         // point to j
	*p = *p / 37   // divide j through the pointer
	fmt.Println(j) // see the new value of j
}
nabeyangnabeyang

deferの一番、ありふれた利用方法はリソースの開放ですね。ファイルの場合はこんな感じです。channelでも使うので、よく使うと思います。

func main() {
  fp, err := os.Open(os.Args[1])
  if err != nil {
        log.Fatal(err)
  }
  defer fp.Close()
  buf, _ := ioutil.ReadAll(fp)
  fmt.Println(string(buf))
}
スースー

使えそうなライブラリ

https://qiita.com/shunsukeaihara/items/ba6472910db885f436a0
↑参考

gojson

  • jsonのデータを渡すとそれに対応するstructを生成
  • JSON APIを利用するときに楽ができる
  • 既存APIのリプレイスをGoでやる時に役立つ
  • 既存APIのJSONの内容を整理しておくべし

goquery

  • JQueryっぽくhtmlをパースしたり検索したりして楽ができる
  • 自前でhtmlのパースを書かないようにするために役立つ

goreq

net/httpパッケージ。

  • httpリクエストを飛ばすのは結構面倒
  • いろんな書き方があったりしてヘッダつけるときどれ使うのか調べるのを楽にする
  • 毎回調べたりするのを楽するときに使うラッパ
  • pythonのrequestsが該当しそう

使い方は公式のREADME見れば一発で分かる。

monkey

  • 関数ポインタ書き換えてMonkey Patchingしてくれる
  • LL言語でのテストコードに慣れてると気軽にMonkey Patchingする人になっている

注意点

  • 無理やり関数ポインタ書き換えるのでセキュアなOSだと動かない
  • インライン化されてるとうまく動作しないため、-gcflags -l-が必要だったりする
  • スレッドセーフでもないので気をつけろ。

使い方

  • 関数置き換え(monkey.Patch)と置き換えたものを戻す(monkey.Unpatch)で関数を置き換える。
  • 置き換え元と置き換え先の関数のインターフェイスを揃えておく必要がある(無いと当然panicする)

特定のインスタンスに生えている関数を置き換える場合

monkey.InstanceMethodmonkey.UnpatchInstanceMethodを利用

render

  • httpレスポンスを楽に返すことが出来る
  • JSONのレスポンス返すのにいちいちNewEncoderとか書いてられない
  • jsonとかBinaryとか返すのが楽になる

validator

  • structのアノテーションを元に、各要素のヴァリデーションするライブラリ

使い方

数値型と文字列型で、よくあるヴァリデーションがアノテーションで書けて楽。

type NewUserRequest struct {
    Username string `validate:"min=3,max=40,regexp=^[a-zA-Z]$"`
    Name string     `validate:"nonzero"`
    Age int         `validate:"min=21"`
    Password string `validate:"min=8"`
}

nur := NewUserRequest{Username: "something", Age: 20}
if valid, errs := validator.Validate(nur); !valid {
    // values not valid, deal with errors here
}

↑よりも新しいらしい↓

interpose

  • net/http向けの便利なmiddleware
  • 既存のwafのmiddlewareをnet/httpで使えるようにするadaptor
  • AWSでFargateの手前に何か噛ませている場合は、当たり前だが、wafのように使うことはできないので注意

goxc

クロスコンパイルが楽になるやつ

channels

  • channelのラッパー集
  • バッファーサイズが無限の奴とか、バッファ・サイズ超えると古いやつから勝手に消えてくれる奴とかが実装されている

cron

  • cron形式の指定時間に、gorutineを動かしてくれる
  • cron形式で書けるので楽。普通のcronと違って秒単位まで指定できる。

Godep

  • 普通にgo getするとmasterの最新のコミットを取ってくる
  • 後方互換性がない変更があると死ぬし、全体で同じ物を共有しているのでメンテしてないコードが死んだりする
  • プロジェクトの毎にライブラリを管理して、Godeps.jsonにcommit idを記録してくれる。
  • Godep経由でbuildやtestを叩くとGOPATHを書き換えて動く。Godeps.jsonから落としなおしてくれるとかはしてくれないのでそこはいけてない。

fresh

プロジェクトのディレクトリを監視して、自動でコンパイルして再起動してくれる。godep使ってる場合はこんな感じのMakefile書いとくと良いかも。

GODEP_PATH := $(shell godep path)
fresh:
	GOPATH=$(GODEP_PATH):$(GOPATH) fresh

プロジェクトのディレクトリにrunner.confというファイルを置いて設定を書くことも出来る。

gobot

arduinoとかRaspberry PiとかEdisonとかその他いろいろなロボットとか基盤をgolangから楽に使えるラッパーライブラリ。

gatt

BLEのgattプロファイルを楽に扱える奴。

このスクラップは2021/10/11にクローズされました