次ログ

次ログ

ゆるりと働いているSREの技術ブログのような何か。趣味の話も書く

Go言語 学習メモ01

とりあえずGo言語の学習をしてみることにしました。

情報を集めるのに結構苦労してるので、備忘録と作業メモを兼ねて、 何をやったのかを随時記録していこうと思います。

目次

Go環境構築

#!/bin/bash
# -*- coding: utf-8 -*-

sudo apt-get install -y golang
sudo apt-get install libgtk2.0-dev libglib2.0-dev libgtksourceview2.0-dev -y
go get github.com/mattn/go-gtk/gtk
go install github.com/mattn/go-gtk/gtk

上記のスクリプトを実行。 GUIも使えるようになりたくてgo-gtkをインストールするも、 JavaFXみたいなGUIエディタがなくてひとまず保留。

インストールしたのはバージョン1.6.2です。

$ go version
go version go1.6.2 linux/amd64

公式を見に行ったら最新バージョンは1.9でした。 早めにバージョンアップしようと思います。

Hello World

package main

import "fmt"

func main() {
  fmt.Println("Hello World")
}

まずはこれがないと始まらないですよね。

コマンドライン引数を使う

CLIツールを作るならこれができないと話にならない。

package main

import (
  "fmt"
  "os"
  "flag"
)

func main() {
  fmt.Println("os.Args : ", os.Args)
  //fmt.Println("os.Args[0] : ", os.Args[0])
  //fmt.Println("os.Args[1] : ", os.Args[1])

  i := flag.Int("intvar", 0, "help msg")
  s := flag.String("strvar", "hoge", "help msg")
  flag.Parse()

  fmt.Println("flag.Args() : ", flag.Args())
  fmt.Println("i : ", *i)
  fmt.Println("s : ", *s)
}

コマンドライン引数を扱う方法は2種類あるみたい。

参考サイト : http://qiita.com/uokada/items/f0e069a751679dcf616d

os.Args

os.Argsは普通のコマンドライン引数っぽい。 pythonでいうsys.argvと同じ感じです。

第1引数(Args[0])にはスクリプト自身が格納されているようで、 入力した値は第2引数(Args[1])から使う感じですね。

$ go run args.go -intvar 1 -strvar aaa
os.Args :  [/tmp/go-build513703329/command-line-arguments/_obj/exe/args -intvar 1 -strvar aaa]
os.Args[0] :  /tmp/go-build513703329/command-line-arguments/_obj/exe/args
os.Args[1] :  -intvar
flag.Args() :  []
i :  1
s :  aaa

flag.Args()

pythonでいうargparse.ArgumentParser()と同じ感じです。 オプション名とデフォルト値、ヘルプメッセージを設定できます。

こちらの場合はflag.Parse()を実行しないと、引数が渡されていないように振る舞うため 、引数を渡してもデフォルト値で初期化されるみたいです。

一瞬悩んだのは、引数で渡された値を使うときはポインタとして使わないといけない点で す。

$ go run args.go 1 2 3
os.Args :  [/tmp/go-build676071249/command-line-arguments/_obj/exe/args 1 2 3]
os.Args[0] :  /tmp/go-build676071249/command-line-arguments/_obj/exe/args
os.Args[1] :  1
flas.Args() :  []
i :  0xc82000e2c8 # ←ここ
s :  0xc82000e3b0 # ←ここ

普通に変数名を指定して使おうとしたらアドレスが表示されて「うん?」ってなりました 。*varnameって感じで指定しないといけないんですねー。

そもそもポインタを使わないといけない言語に触るのが随分ぶりなので、違和感バリバリ です。

ひとまず、コマンドライン引数を使うときは、flag.Args()を使っておけばよい感じです かね。

:= って何?

ここでちょっと疑問。 := っていう不思議な代入式が何なのか気になりました。

package main

import "fmt"

func main() {
  var i = 1
  j := 2
  fmt.Println(i)
  fmt.Println(j)
}

こんなコードを動かしても普通に動いたのでなんでだろう? と思ってググったらどうもローカル変数にのみ使える記法だそうです。

参考サイト : http://www.geocities.jp/m_hiroi/golang/abcgo01.html

:= をグローバルスコープにかいてみる

ソースコード

package main

import "fmt"

a := 3
func main() {
  var i = 1
  j := 2
  fmt.Println(i)
  fmt.Println(j)
  fmt.Println(a)
}

実行結果

$ go run var.go 
# command-line-arguments
./var.go:5: syntax error: non-declaration statement outside function body

つまり、varで変数を定義してあればグローバル変数で、:=で変数を定義してあればロー カル変数、って感じでコードを読み解くためにある記法...、ということなのでしょうか ...

単純に人間が読みやすいようにするために導入されてるなら、インデントなりスコープな りで判断がつく気がするので、何かしら他の役割もあるってことなのでしょうか。

おいおい調べようと思います。

その他

端末で go fmt と入力すると、実行したカレントディレクトリ内のgoファイルが整形される。 これ結構便利ですね。

試しに下記のコードをgo fmtしてみました。

package main

import "fmt"

func main() {
  tmpvar := 1 // int var
  hyperverylongvarname := "very long string" // string var
  var tmptmpvar string // var test
  if ( true ) { fmt.Println("true") }
}

結果は、下記のようになってました。

package main

import "fmt"

func main() {
    tmpvar := 1                                // int var
    hyperverylongvarname := "very long string" // string var
    var tmptmpvar string                       // var test
    if true {
        fmt.Println("true")
    }
}

変更されていたのは下記の部分です。

  1. 半角スペースインデントをタブインデントに
  2. インラインコメントの桁
  3. 不要な ( ) の削除
  4. { に改行を挿入

結構これって重要な機能だと思います。

僕は半角スペースでインデントする人ですけれど、 どっちかに統一するのって結構大変なので、 プログラムが勝手に整えてくれるのは大助かりです。

まとめ

今回はGoをLinuxMint環境にインストールして、 シンプルな標準出力とコマンドライン引数を使う方法を学習しました。

シンプルな仕様といっても覚えないといけないことはたくさんありますね。 地道に学習していこうと思います。

Go言語の勉強をする目的は、Pythonでかいた画像処理スクリプトPython実行環境のないWindows環境用に配布するためです。

なので、なるべく早いうちに画像処理系の機能の使い方を学習しようと思っています。

以上です。