CLI作成で使うパッケージ② spf13/viper

Topic

configuration周りは spf13/viper を利用する

Summary

viperは以下をサポートしている

  • setting defaults
  • reading from JSON, TOML, YAML, HCL, envfile and Java - properties config files
  • live watching and re-reading of config files (optional)
  • reading from environment variables
  • reading from remote config systems (etcd or Consul), and - watching changes
  • reading from command line flags
  • reading from buffer
  • setting explicit values

Pro Tip: Keep Viper Isolated → Config Packageを用意する

https://carolynvanslyck.com/talk/go/cli/#/sting-of-the-viper

→ the configuration was loaded once

→ App structをリファクタ

https://carolynvanslyck.com/talk/go/cli/#/app-with-config-pkg

  • App take in a config load it up
  • save that struct
  • work with it

How's day been?

Good 😉

Graph representation 隣接リストでのグラフ表現

Topic

グラフ表現の復習

※自分用のまとめノートなので、誤った認識で書かれてる可能性あり

Graph representation

今回は基本の隣接リストでのグラフ表現の実装の復習。

ちなみに、グラフ表現では大きく4種類の方法があるらしい。*1

f:id:mizushou:20201228042419p:plain

やりたいこと

こんなグラフや、あんなグラフをコード上で表現して、BFS,DFSなどで走査(検索)したい

f:id:mizushou:20201228042057p:plainf:id:mizushou:20201228042248p:plain

Adjacency lists

  • array Adj of $|V|$
  • each element in the array is a pointer to a linked list
  • for each vertex $v \in V$, Adj[v] stores $v$'s neighbors
  • ${ v \in V | (u,v) \in E }$ directed
  • ${ v \in V | {u,v} \in E }$ undirected

Adjacency listの例

  • $|V| = 3$
  • $|E| = 4$
  • Space complexity : $\Theta(|V|+|E|)$
    • Undirectedの時はEdgeが2倍だが $\Theta(|V|+|E|)$
f:id:mizushou:20201228042454j:plainf:id:mizushou:20201228042504p:plain

Adjacency listの実装

  • 一番単純なのはArray (ArrayList)で実装する方法。あとは Dictionary (HashTable)など
  • 各要素の入れ物(隣接するノードをいれる)を何にするかも実装者による
  • 今回は以下のように実装した

    • Adjacency list自体はDictionay (HashMap)
    • 各要素はSet (HashSet)
    • メリットは、同じ辺を追加してしまった時に重複してAdjacency listに登録されることがない

      java private HashMap<Integer, HashSet<Integer>> adjacencyList;

  • Adjacency listのインターフェース

    • インターフェースを用意してみた
    • 実際は配列orハッシュテーブルに↑の図のように頂点を追加できればいいだけなので、object oriented likeにやる必要はない
    • 辺の追加( addDirectedEdge addUnDirectedEdge)、指定した頂点に隣接する頂点を返す( neighbors )メソッドはBFS, DFSを実行する上で必要
    • 最後にデバッグ用に printGraphも定義した
public interface Graph {

    public void addDirectedEdge(int i, int j);
    public void addUnDirectedEdge(int i, int j);
    public HashSet<Integer> neighbors(int i);
    public void removeEdge(int i, int j);
    public boolean hasEdge(int i, int j);
    public List<Integer> inEdge(int i);
    
    public void printGraph();
}
public static void main(String[] args) {

        // #1 Directed
        // Create the graph
        int V = 3;
        GraphAsAdjList graph = new GraphAsAdjList(V);

        graph.addDirectedEdge(0,2); // a -> c
        graph.addDirectedEdge(1,0); // b -> a
        graph.addDirectedEdge(1,2); // b -> c
        graph.addDirectedEdge(2,1); // c -> b

        graph.printGraph();
}
vertex 0|-> 2
vertex 1|-> 0-> 2
vertex 2|-> 1

参考にしたもの

raw string literals and interpreted string literals.

Topic

string literalには raw string literalinterpreted string literal の二種類がある

The Go Programming Language Specification

Summary

raw string litreral

  • バッククォートで囲む
  • 名前の通り、改行などがそのまま使える
  • \ が特別な意味を持たない
`foo`

interpreted string literal

  • ダブルクォートで囲む
  • 改行は使えない。ダブルクオーテーションも \エスケープが必要
  • \ のバックスラッシュエスケープでrune literalが使える -> \n など
"bar"

その他

Sho372/golang-programming

細かいことがほかにもあるがひとまずこんな感じ

rune literalもある

How's day been?

Bad 😅

typed/untyped constant

Topic

golangのconstantについて

The Go Blog

Summary

constantにはtypedとuntypedの二種類がある

Default type

typed

const typedHello string = "Hello, world"

untyped

"Hello, world"
const hello = "Hello, world"

この場合、 str のtypeは?

//右オペランドはuntyped constant
str := "Hello, world"

untyped constantは default type がある

↑の場合は、"Hello, world" のdefault typeはstring → strのtypeはstring

The answer is that an untyped constant has a default type, an implicit type that it transfers to a value if a type is needed where none is provided.

なので、これも同じ

var str = "Hello, world"

最後に

変数はuntypedない

How's day been?

Good 😉

CLI作成で使うパッケージ① spf13/cobra

Topic

今回、CLI作成で使うパッケージ① → cobra

spf13/cobra

cobraが使われているプロジェクト

spf13/cobra

Summary

以下、cobraに依存する機能

  • CLI Framework / Main Entry point
  • Command Routing
  • Error Handling
  • Help Text (Don't forget to customize!)
  • Flag Parsing and Validation

今までは、フラグパースはflag packageを使っていた

flag - The Go Programming Language

Recommended PracticeはCreate an application package

How's day been?

Good 😉

Package level scope

Topic

Package level scopeの変数

Summary

変数を定義する時に var キーワードを使うが、定義する場所でスコープが変わる。(package levelとfunction level)

package main

import "fmt"

var c, python, java bool ← at Package level
 
func main() {
    var i int ← at Function level
    fmt.Println(i, c, python, java)
}

var キーワード

  • declareで使う
  • assignは明示的にしてもしなくてもいい
    • しない場合は ZERO VALUE がassignされる
  • typeも明示的に定義してもしなくてもいい
  • scopeは定義する場所で変わる

    • Package scope
    • Function scope
  • ZERO VALUE golang.org

How's day been?

Bad 😅

CLIの設計

Topic

golangCLIを(しっかり設計して)作ってみる。設計で意識するところ

Summary

Sentence Readability

Antipattern

  • Avoid positional arguments where the order matters

emote add repo funk https://x.com/funk.json 🤔

emote add repo https://x.com/funk.json funk 😓

emote add repo funk --url https://x.com/funk.json

3つ目が好みだと言っている。

第1引数~3引数はpositional → lnとかの順序に合わせる → ここまではユーザーが推測しやすい

ln -s <File name> <Link name> を連想する可能性が高いので認識コストが低いはず

4つ目はパラメーターにしちゃう。こうすると順序問題は関係なくなる

自動化のサポート

  • —outputコマンドでjsonなりmachine readableな形式でも出力できるようにしてあげる

Implicit Resources in the Domain

$emote list

helpのカスタマイズ

よくある全てのオプションやフラグについてのhelpよりも、ユーザーが何をすべきかのガイダンスを表示するほうがいい

f:id:mizushou:20201214083805p:plain

Piping is good for automation but people don't want to pipe

golang cobra 使い方ググるCLIの記事が結構出てくる

次回は21:43あたりのLet's build a CLI!から

How's day been?

Good 😉