3月1週

土曜:1h,2h,2h,3h=8h

発見

  • middlewareに外部APIとの接続を書いてserviceとしてセットする
  • 以下例(YouTubeAPIとの接続)
package middlewares

import (
    "context"
    "os"

    "github.com/labstack/echo"
    "github.com/sirupsen/logrus"
    "google.golang.org/api/option"
    "google.golang.org/api/youtube/v3"
)

func YouTubeService() echo.MiddlewareFunc {
    return func(next echo.HandlerFunc) echo.HandlerFunc {
        return func(c echo.Context) error {
            key := os.Getenv("API_KEY")

            ctx := context.Background()
            service, err := youtube.NewService(ctx, option.WithAPIKey(key))
            if err != nil {
                logrus.Fatalf("Error creating YouTube service: %v", err)
            }

            c.Set("yts", service)

            if err := next(c); err != nil {
                return err
            }

            return nil
        }

    }
}

Nuxtでの認証情報の永続化

  • npm install --save cookie-universal-nuxt

途中で終わったので日曜日へのメモ

  • signUp.vueの中でcookieへのセットを行う(同階層にmixinを作る)
  • actionではtokenのmitationまでを行う

日曜:2h,2h,2.5h=6.5h

結局cookie-universal-nuxtはTypeScript環境では使えなそうだったのでuniversal-cookieを使うことに・・・

  • で、ミドルウェアを各ページで効かせたい場合はnuxt.config.tsには書かずに、pagesのComponentの登録のところで書く

@Component({
  middleware: 'authed',
  components: {
    Logo,
    VuetifyLogo,
    BmDialog
  }
})

データベースとのやりとりはgormを使う

  • テーブルに対応するモデルを struct を作って表現する

76

月曜:11h

  • どういうときにポインタ型(*)を付与すればいいのかイマイチわらかずにいる
  • 現状の理解は、Vueで言うと子コンポーネントで値を更新するときには$emitを使うというときに似ているような気がする。
  • つまり、メソッド内でそのインスタンスの値を変える処理をしているメソッドのときは、紐づけ(メソッドの前に型をつけるパターン)時にポインタ型を指定する

  • タイプアサーション

  • 関数の引数にinterface{}を渡すとどんな引数でも受け取るようにできる
  • その際は関数のなかで型を合わせる必要がある
func do(i interface{}){
  do(10)
  do("mike")
  do(true)
}
  • switch-type文
switch v := i.(type) {
  case int:
  // 処理
  case string:
  // 処理
}

qiita.com

qiita.com

火曜:11h

  • golangのカスタムエラー作成

golang.hateblo.jp

  • Customなerrorを作るときははポインタレシーバとして定義しアンパサンドを付与する
  • エラー内容を比較するとき、値渡しだとよろしくない・・

  • app側からDBマイグレーションを実施する

  • docker-compose exec app go run tools/migration.go
  • databases/mysql.goで接続情報を記述。。railsで言うdatabase.ymlをソースに書いているイメージ
  • 以下のDB_HOST部分はdockerで環境構築している場合はデータベースのコンテナ名が入る
  • マイグレーションに成功したら以下のようになる f:id:yosuke0517:20200303233516j:plain
// Memo:"DB_HOST"はdockerの場合データベースコンテナ名
db, err = gorm.Open("mysql",
        os.Getenv("DB_USERNAME")+":"+os.Getenv("DB_PASSWORD")+
            "@tcp("+os.Getenv("DB_HOST")+":"+os.Getenv("DB_PORT")+")/"+
            os.Getenv("DB_DATABASE")+
            "?charset=utf8mb4&parseTime=True&loc=Local")

今日の成果:バックエンド(golang)でお気にいり機能実装

  • まだエラーある(明日終了予定)

水曜:11h

API開発も佳境:

  • お気にいりに追加機能は認証を前提とすることにしたのでポストにはトークンを付与する。ターミナル で確認する時は以下のようにする
  • -H オプションで任意のリクエストヘッダを指定。REST API の認証に使われる Authorization ヘッダの指定例は以下
curl -XPOST -H ’Authorization: Bearer {トークン}' 'http://localhost:8080/api/favorite/{なにかしらのID}/toggle'
  • 以下をnullだった場合とundefinedだった場合で検証しなきゃ
  • この式は左辺値がundefinedだった場合に右辺値が返る
  • params.isFavorite = payload.isFavorite || false

木曜:11h

  • golangで無名関数
  • 変数に入れることができる
f := func(){
  for i := 0; i < 10; i++ {
    //c["key"] += 1
    c.Inc("key")
  }
}
f()// 実行
  • 即時実行の場合は以下のように最後に()をつける
func(){
  for i := 0; i < 10; i++ {
    //c["key"] += 1
    c.Inc("key")
  }
}()

goroutine

  • sync.WaitGroup

    • ある処理が終わるまで待って欲しいときに使う
  • channel

    • 各goroutine間でのデータのやり取りをする窓口。使い終わったらcloseしないといけない。
  • buffered channel

    • channelの初期化時にchannelの数を指定できる。
  • channelのrangeとclose

    • チャネル受信をループ化しチャネルがcloseしたらループが終了するように書ける
  • producerとconsumer

    • ちょっとまだわからない生産者と消費者的な?
  • fan-out fan-in

    • goroutine間で値を出し入れする
  • channelとselect

    • 複数 channel を同時に待ち受けるselectで分岐
  • default section

    • selectを使った場合に当てはまる値がないとき(javascriptでいうcase文みたいな)
  • outerloop

    • ループ処理を抜けるときの書きかた
  • sync.Mutex

    • 1つのgoroutineで値を共有するとき(channelを使わないやり方)
type Counter struct{
  v map[string]int
  mux sync.Mutex
}

func (c *Counter) Inc(key string){
  c.mux.Lock()// ロックをかける
  defer c.mux.Unlock()// ロックを解除
  c.v[key]++
}


func (c *Counter) Value(key string){
  c.mux.Lock()// ロックをかける
  defer c.mux.Unlock()// ロックを解除
  c.v[key]++
}

func main(){
  c := Counter{v: make(map[string]int)}
  //c := make(map[string]int) //key:string, value:intのマップを生成
  // 無名関数?的なやつで実行
  go func(){
    for i := 0; i < 10; i++ {
      //c["key"] += 1
      c.Inc("key")
    }
  }() // 定義&実行するときは()をつける?
  
  go func(){
    for i := 0; i < 10; i++ {
      //c["key"] += 1
      c.Inc("key")
    }
  }()
  
  time.Sleep(1 * time.Second)
  fmt.Println(c, c.Value("key"))
}

金曜:8h

  • ようやく形になってきた

f:id:yosuke0517:20200306234047j:plain

  • でもtokenの有効期間を忘れていたり(1時間)NuxtがSSRだから画面遷移時のcookieが取得できなかったりハマった。。。

  • firebase.google.com

週次報告

  • 年間(2019/8~2020/8)目標時間(業務での設計・実装含む):3380h
  • 今週を含む累積時間:1886.5h
  • 週次目標時間:65h
  • 週次実績時間:66.5h
  • 何を得たか:golang基礎, Nuxt.jsのSSR時の注意点
  • 何が必要か:golang基礎
  • 来週の目標:ポートフォリオデプロイ