実験レポート
実験内容
- プロジェクトを管理するための go コマンド ライン ツールに精通している
- Go の関数、データ構造、インターフェイスを包括的に使用して、シンプルなコマンドライン アプリケーション アジェンダを作成します。
- オブジェクト指向の考え方を使用して、プログラムに適切な構造コマンドがあり、他のコマンドのコードに影響を与えることなく新しいコマンドで簡単に変更および拡張できるようにプログラムを設計します。
- プロジェクトは Github 上にデプロイされており、複数人によるコラボレーション、特にコードのマージに適しています。
- サポートログ(原則としてデバッガは使用しません)
実験手順
1.コブラをインストールする
- コマンドで
go get -v github.com/spf13/cobra/cobra
ダウンロードする際に以下のエラーが表示されますが、これは壁のせいで公式サイトから直接ダウンロードできないため、githubで直接入手する別の方法をとります。
Fetching https://golang.org/x/sys/unix?go-get=1
https fetch failed: Get https://golang.org/x/sys/unix?go-get=1: dial tcp 216.239.37.1:443: i/o timeout
- まず $GOPATH/src/golang.org/x ディレクトリに cd し、git clone を使用して sys プロジェクトと text プロジェクトをダウンロードします。
sys: git clone https://github.com/golang/sys
text: git clone https://github.com/golang/text
- 上記 2 つの依存関係をインストールした後、次のコマンドを使用して cobra をインストールします。インストール後、cobra 実行可能プログラムが
$GOBIN
の下に。
go install github.com/spf13/cobra/cobra
2. コブラの小さなケースを完成させます
agenda register -uTestUser
コマンドまたはを処理するagenda register --user=TestUser
小さなプログラムを作成します。
- $GOPATH/src にフォルダーを作成し、フォルダー名をカスタマイズします。
cd $GOPATH/src
mkdir Test
- ファイルを入力し、次のコマンドを使用して cobra を初期化します (Test はコマンド名です)。初期化が成功すると、cmd フォルダー、証明書およびファイルがフォルダー内に生成されます
main.go
。
cobra init --pkg-name Test
- 初期化が成功した後も、コマンドを追加する必要があります。次のコマンドを使用して、
register
コマンドの名前であるコマンドを追加します。追加が完了すると、cmd フォルダーにファイルが生成され、register.go
コマンドファイルに設定できます。
cobra add register
- 変更
register.go
、init()
追加
registerCmd.Flags().StringP("user", "u", "Anonymous", "Help message for username")
Run
匿名コールバック関数に以下を追加します。
username, _ := cmd.Flags().GetString("user")
fmt.Println("register called by " + username)
- テストコマンド
go run main.go register --user=TestUser
register called by TestUser
3. JSON のシリアル化と逆シリアル化
json パッケージにはサポートが組み込まれています。ドキュメントの場所は: https://go-zh.org/pkg/encoding/json/ です。json の使用例を以下に示します。
- コーディング
- まずはjsonパッケージファイルを導入します。
import (
"encoding/json"
"fmt"
)
- 次に構造を定義します
type Message struct {
Name string
Body string
Time int64
}
- 構造体を定義した後、その構造体を使用して、その構造体をインスタンス化します。
m := Message{"Alice", "Hello", 1294706395881547000}
- インスタンス化後、json の Marshal 関数を使用して json をエンコードします。
b, err := json.Marshal(m)
- エンコードの完了後に結果を印刷できます。
fmt.Print(b)
{"Name":"Alice","Body":"Hello","Time":1294706395881547000}
- デコード
- デコードではまず構造体変数を定義します
var m Message
- 次に、json の Unmarshal 関数を使用して json をデコードし、上で定義した構造体変数をパラメーターとして渡します。その後、構造体変数に対応するメンバー変数に対応する値が割り当てられます。
err := json.Unmarshal(b, &m)
4. コマンド設計
ユーザー登録
agenda register -u username -p password - e email -t telphone
ユーザーがこのコマンドを入力すると、登録操作が実行されます。ユーザーは次の 4 つのパラメーターの値を指定する必要があり、指定しないと作成は失敗します。登録が成功すると、ユーザーの情報がコンピュータに保存されます。
パラメータ:
- –ユーザー名/-u: ユーザー名
- –password/-p: パスワード
- –email/-e: 電子メール
- –telphone/-t: 電話
コード:
func createUser(users []User, username string, password string, email string, telphone string) {
if err := validate(users,username,password,email,telphone); err != nil{
//check user info
fmt.Println(err)
return
} else {
//add new user to list
users = append(users,User{username,password,email,telphone})
//sync the user info to file
WriteUserToFile(users)
fmt.Println("User register success")
}
}
- ここでの登録は、ユーザーが入力した登録情報が正しいかどうかをvalidate関数で判定する必要があり、間違っている場合はエラーメッセージを返し、正しければメモリ上の変数に情報を追加します。 、実体化を使用して永続化されます。
ユーザーログイン
agenda login -u username -p password
ユーザーがこのコマンドを入力すると、ユーザーはログインします。ユーザーは次の 2 つのパラメーターの値を指定する必要があります。その後、プログラムはコンピューターに保存されているアカウントとパスワードのペアを照合します。照合が成功すると、ステータスは、ログインしている対応するユーザーに設定されます。失敗した場合は、エラー メッセージが返されます。
パラメータ:
- –ユーザー名/-u: ユーザー名
- –password/-p: パスワード
コード:
if isLogin() {
fmt.Println("Please logout first!")
return
}
//validate username and password
if len(username) == 0 || len(password) == 0 {
fmt.Println("Need a username and a password")
return
}
for _,user := range users{
if user.Username == username && user.Password == password{
WriteCurUserToFile(user.Username)
fmt.Println("Login success! Username is " + user.Username + "!")
return
}
}
- ここでは、クライアントがログインしたかどうかを判断する必要があります。これは後続の具体化によって実現され、ユーザー リストからユーザー名とパスワードが一致するユーザーが存在するかどうかを判断し、存在する場合はログイン済みに設定されます。州。
ユーザーのログアウト
agenda logout
ユーザーがこのコマンドを入力すると、ユーザーはログアウトします。ユーザーはパラメータを指定する必要はありません。プログラムはコンピュータに保存されている一時ファイルに基づいてログイン ステータスを決定します。ユーザーがログインしている場合は、次のようになります。ログアウト状態に戻し、ログアウト情報を返します。ログインしていない場合はエラーメッセージを返します。
キーコード:
fmt.Println("user logout")
if isLogin() {
//only can logout after login
WriteCurUserToFile("logout")
fmt.Println("Logout success!")
} else {
fmt.Println("Logout failed! Please login first!")
}
- ユーザーログアウトは、その後の実体化結果を利用して、クライアントの状態をログアウト状態に設定し、ログアウト情報を出力します。
ヘルプのヒント
アジェンダヘルプ [コマンド]
コマンドパラメータが指定されている場合はコマンドの使用方法が表示され、パラメータが指定されていない場合はすべてのコマンドが表示されます。
if (len(args) == 1) {
if args[0] == "register" {
fmt.Println(registerStr)
} else if args[0] == "login" {
fmt.Println(loginStr)
} else if args[0] == "logout" {
fmt.Println(logoutStr)
}
} else {
fmt.Println(registerStr)
fmt.Println(loginStr)
fmt.Println(logoutStr)
}
5. データの実体化
- io の ioutil 言語パッケージをインポートする
import "io/ioutil"
- ユーザー情報の読み取り
func ReadUserFromFile () ([]User, error){
//read every users info
var users []User
if data, err := ioutil.ReadFile(UserInfoPath); err == nil {
str := string(data)
json.Unmarshal([]byte(str), &users)
return users, nil
} else {
return users, err
}
}
ここでは、ioutil の ReadFile 関数を使用して、ファイル内のすべてのバイトをデータ バイト配列に直接読み取り、文字列に変換し、その文字列を JSON にデコードします。
- ユーザー情報を書き込む
func WriteUserToFile (users []User){
//write user info to file
if data, err:=json.Marshal(users); err == nil {
ioutil.WriteFile(UserInfoPath,[]byte(data),os.ModeAppend)
} else {
panic(err)
}
}
ここでは ioutil の WriteFile 関数が使用されており、まず構造が json エンコードされ、次に json 化された配列がファイルに書き込まれます。
- ログイン状況記録
func WriteCurUserToFile (curUser string) {
//set the login status
if err := ioutil.WriteFile(curUserPath,[]byte(curUser),os.ModeAppend); err != nil {
panic(err)
}
}
func ReadCurUserToFile() (string, error){
//check the login status
if data, err := ioutil.ReadFile(curUserPath); err == nil {
return string(data), nil
} else {
return string(data), err
}
}
また、ログイン状態を記録するためにフォルダを使用し、ログイン状態を変更するための 2 つの機能が与えられています。
6. ログサービス
- ログ サービスは、go 言語のログ パッケージを使用して実装されます。
import "log"
- まず、ファイルにログを書き込むための Logger を定義します。ここではエラー ログと操作情報ログの 2 つを定義します。
var (
Error * log.Logger
Login * log.Logger
)
- 次に、ログ ファイルの操作ライター ハンドルを取得します。ここでは、err とログ ファイルをそれぞれ取得します。
loginlog, err :=os.OpenFile(logpath,os.O_RDWR|os.O_CREATE|os.O_APPEND,0666)
if err !=nil{
log.Fatalln(err)
}
errlog, err := os.OpenFile(errpath,os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
log.Fatalln("file open error : %v", err)
}
- 最後に、ログ パッケージの New 関数を使用してロガーを作成します。
Error = log.New(errlog, "ERROR: ", log.Ldate|log.Ltime|log.Lshortfile)
Login = log.New(loginlog, "LOG: ", log.Ldate|log.Ltime|log.Lshortfile)
- 使用すると、標準出力と同様になります。
Login.Println("login info")
Error.Println("error info")
プログラムのテスト
- まず、プログラム フォルダー内のコマンドを使用し
go install agenda
てインストールします。その後、$GOPATH/bin ディレクトリにアジェンダ実行可能ファイルが生成され、そのディレクトリをパス環境変数に追加します。アジェンダ コマンドを直接使用して実行できます。それ。 - ユーザーを作成
- ユーザー名が重複しているというエラーメッセージ
- ユーザーログイン
- すでにログインしている状態でログインする
- ユーザーのログアウト
- 再度ログアウトします
- ロギング
- ヘルプのヒント
- オンライン化する