20201124のGoに関する記事は6件です。

Client-goでLabelSelectorを使って指定したラベルのPodのみを抽出したい

やりかた

  • metav1.ListOptionsの中で定義する
  • LabelSelector以外にもいろいろある

該当部分

    pods, err := clientset.CoreV1().Pods(namespace).List(context.TODO(), metav1.ListOptions{
        LabelSelector: "app=vamdemic111aaa-app",
    })

全体

package main

import (
    "context"
    "encoding/json"
    "fmt"
    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    "k8s.io/client-go/kubernetes"
    "k8s.io/client-go/tools/clientcmd"
    "log"
    "os"
    "path/filepath"
)

func main() {
    // Kubeconfigのファイルパスを指定
    kubeconfig := filepath.Join(os.Getenv("HOME"), ".kube", "config")
    config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
    if err != nil {
        log.Fatal(err)
    }

    // Kubeconfigを読み込む
    clientset, err := kubernetes.NewForConfig(config)
    if err != nil {
        log.Fatal(err)
    }

    // Pod一覧を呼び出す
    namespace := "default"
    pods, err := clientset.CoreV1().Pods(namespace).List(context.TODO(), metav1.ListOptions{
        LabelSelector: "app=vamdemic111aaa-app",
    })
    if err != nil {
        log.Fatalln("failed to get pods:", err)
    }

    m := map[string]string{}

    for _, pod := range pods.Items {
       m[pod.Name] = string(pod.Status.Phase)
    }

    data, _ := json.Marshal(m)
    fmt.Printf(string(data))
}

参考

https://blog.nnn.dev/entry/2019/12/21/144550

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

GitHub ActionsでGoアプリをGoogle App Engineにデプロイする

TL;DR

GitHub ActionsでGoアプリをGoogle App Engineにデプロイするには色々な方法が存在していたようだが,現在はGoogleの提供するgoogle-github-actions/setup-gcloudと言うActionを使うのが良いらしい.
https://github.com/google-github-actions/setup-gcloud

Secretsの設定

GCP_PROJECT_IDにGCPのプロジェクトIDを設定する.
GCP_SA_KEYにGCPのサービスアカウントの鍵を設定する.サービスアカウントはデフォルトのもので良い.別サービスから移行する場合は忘れずに過去の鍵を削除しておく.

workflowファイル

github/workflows/deploy.yml
name: "Deploy"

on: 
  push:
    branches:
      - master

jobs:
  deploy:

    runs-on: ubuntu-latest

    steps:
    - name: Checkout repository
      uses: actions/checkout@v2

    - name: Set up Cloud SDK
      uses: google-github-actions/setup-gcloud@master
      with:
        project_id: ${{ secrets.GCP_PROJECT_ID }}
        service_account_key: ${{ secrets.GCP_SA_KEY }}
        export_default_credentials: true

    - name: Use gcloud CLI
      run: gcloud app deploy --quiet app/web/app.yaml

最初--quietをつけ忘れてエラーになってしまった.

まとめ

思ったより簡単にGitHub Actionsに移行できた.みんな使おう!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

GoのnilスライスはFirestoreだとnullになるから気をつける

問題

GoでFirestoreのドキュメントにデータを書き込んでいて、配列を期待するフィールドに何故かnullが入っていて不思議になった。
データの型としても

type Fuga struct {
    Hoge        []string         `firestore:"hoge"`
}

だし、スライスに何も入ってなかったらFirestore側には空配列入って終わりでしょって思ってた。

スライスのゼロ値はnil

https://godoc.org/cloud.google.com/go/firestore#DocumentRef.Create の以下の文章を見るに、Firestoreはあらゆる型の nilnull に扱うらしい。

nils of any type convert to Null.

スライスのゼロ値はnilなので、ただ構造体を初期化しただけだとスライスはnilのまま -> そのままfirestore側に保存するとnullになるということのようだった。
なので、構造体を初期化する時にスライスも make 使うなりしてnilではない空のスライスを作ってあげることを意識した方が良いなと思った。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

CleanArchitecture的な構成のGo言語サーバー サンプルコード(echo, wire利用)

はじめに

CleanArchitecture的なパッケージ構成に照準を合わせてGoのREST API Serverの実装をしてみる。
更にGoのweb framework echoとDI code generatorであるwireを組み込む。

excuse

この構成で本番稼働実績が有る訳ではなく、まずは叩き台的に考えてみました。
まだ改善の余地は有りそうです。

実装リポジトリ

img

*利用方法はREADMEを参照。

ディレクトリ構成

├── cmd
│   └── server
├── db
├── domain
│   ├── model
│   └── repository
├── handler
├── infra
│   └── mysql
├── response
├── router
└── usecase

cmd

sever起動のmainファイル。

db

dbへの接続情報。
migration情報もここに置くかもしれない。
infraに置いても良いかもしれない。

domain/model

単一エンティティのドメインロジックはこちらに記述。

domain/repository

永続化情報のインターフェイス。

handler

echoのエンドポイント処理から呼ばれるハンドラ郡。
ここでwireを使いDependeny Injectionする構成とした。

infra

永続化処理の実装詳細。

response

要件に応じてこちらでレスポンスフォーマットを決める。

router

echoのルーティング エンドポイント定義を集約する。

usecase

ドメインロジック以外のアプリケーションロジックをこちらに記述。

更に実装する場合の検討ポイント

DBトランザクションどこに置く?

usecase内でbeginして引数にDBセッション持ち回るくらいが収まりが良さそうな気がしている。
(infraに永続化実装詳細が収まってないが、、)

レイヤーが分離してない?

もっと厳密にやるならinfraで構造体に別途DBタグを用意してmodelと相互変換してもよさそうだが出来ればmodel structをそのまま持ち回って手数を減らしたい。

sqlでtable joinとかしたら?

domain/serviceにてネストした構造体を用意してinfraでクエリ結果を受け取れば良い?

type (
    Joined struct {
        Example
        Example2
    }
)

参考

Clean Architecture 達人に学ぶソフトウェアの構造と設計
https://github.com/golang-standards/project-layout
https://future-architect.github.io/articles/20200528/

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

CleanArchitecture的な構成のGo API サーバー サンプルコード(echo, wire利用)

はじめに

CleanArchitecture的なパッケージ構成に照準を合わせてGoのREST API Serverの実装をしてみる。
更にGoのweb framework echoとDI code generatorであるwireを組み込む。

excuse

この構成で本番稼働実績が有る訳ではなく、まずは叩き台的に考えてみました。
まだ改善の余地は有りそうです。

実装リポジトリ

img

*利用方法はREADMEを参照。

ディレクトリ構成

├── cmd
│   └── server
├── db
├── domain
│   ├── model
│   └── repository
├── handler
├── infra
│   └── mysql
├── response
├── router
└── usecase

cmd

sever起動のmainファイル。

db

dbへの接続情報。
migration情報もここに置くかもしれない。
infraに置いても良いかもしれない。

domain/model

単一エンティティのドメインロジックはこちらに記述。

domain/repository

永続化情報のインターフェイス。

handler

echoのエンドポイント処理から呼ばれるハンドラ郡。
ここでwireを使いDependeny Injectionする構成とした。

infra

永続化処理の実装詳細。

response

要件に応じてこちらでレスポンスフォーマットを決める。

router

echoのルーティング エンドポイント定義を集約する。

usecase

ドメインロジック以外のアプリケーションロジックをこちらに記述。

更に実装する場合の検討ポイント

DBトランザクションどこに置く?

usecase内でbeginして引数にDBセッション持ち回るくらいが収まりが良さそうな気がしている。
(infraに永続化実装詳細が収まってないが、、)

レイヤーが分離してない?

もっと厳密にやるならinfraで構造体に別途DBタグを用意してmodelと相互変換してもよさそうだが出来ればmodel structをそのまま持ち回って手数を減らしたい。

sqlでtable joinとかしたら?

domain/serviceにてネストした構造体を用意してinfraでクエリ結果を受け取れば良い?

type (
    Joined struct {
        Example
        Example2
    }
)

参考

Clean Architecture 達人に学ぶソフトウェアの構造と設計
https://github.com/golang-standards/project-layout
https://future-architect.github.io/articles/20200528/

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

LeetCodeに毎日挑戦してみた 21. Merge Two Sorted Lists(Python、Go)

はじめに

無料英単語サイトE-tanを運営中の@ishishowです。

プログラマとしての能力を上げるために毎日leetcodeに取り組み、自分なりの解き方を挙げていきたいと思います。

Leetcodeとは

leetcode.com
ソフトウェア開発職のコーディング面接の練習といえばこれらしいです。
合計1500問以上のコーデイング問題が投稿されていて、実際の面接でも同じ問題が出されることは多いらしいとのことです。

Go言語入門+アルゴリズム脳の強化のためにGolangとPythonで解いていこうと思います。(Pythonは弱弱だが経験あり)

7問目(問題21)

21. Merge Two Sorted Lists

  • 問題内容(日本語訳)

2つのソートされたリンクリストをマージし、新しいソートされたリストとして返します。新しいリストは、最初の2つのリストのノードをつなぎ合わせて作成する必要があります。

Example 1:

img

  Input: l1 = [1,2,4], l2 = [1,3,4]
  Output: [1,1,2,3,4,4]

Example 2:

  Input: l1 = [], l2 = []
  Output: []

Example 3:

  Input: l1 = [], l2 = [0]
  Output: [0]

考え方

  1. 新規ListNodeを作成
  2. 作成したListNodeの参照をresという変数に渡す
  3. ループを回して、l1、l2のvalが小さいほうを進めてcurに代入する
  4. どちらかが終点まで行くとループが終わるので残りも代入する。
  5. returnはresにする 最初は0のためその次から
  • 解答コード
class Solution(object):
    def mergeTwoLists(self, l1, l2):
        cur = ListNode(0)
        res = cur
        while l1 and l2:
            if l1.val < l2.val:
                cur.next = l1
                l1 = l1.next
            else:
                cur.next = l2
                l2 = l2.next
            cur = cur.next
        cur.next = l1 or l2
        return res.next  
  • Goでも書いてみます!
func mergeTwoLists(l1 *ListNode, l2 *ListNode) *ListNode {
    cur := &ListNode{}
    res := cur
    for l1 != nil && l2 != nil {
        if l1.Val < l2.Val {
            cur.Next = l1
            l1 = l1.Next
        } else {
            cur.Next = l2
            l2 = l2.Next
        }
        cur = cur.Next
    }
    if l1 != nil {
        cur.Next = l1
    } else if l2 != nil {
        cur.Next = l2
    }

    return res.Next
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む