背景
Go言語よくわからないので学習したメモを残す
Go言語特徴・メリット
構文がシンプル
C言語を基本としながらも文末のセミコロン不要といった、ソースコード量が少ない
(Rubyもセミコロン不要)
コンパイルが速い
- 構文がシンプルになった。
- includeファイルを採用していない。
といったことから、C言語系のコンパイラに比べ速い。
並列処理をサポート
複数の処理を同時にかつ効率的に実行可能。「ゴルーチン」という単位で管理されている。
GCサポート
安全性が高い(バグによるメモリ破壊を回避)
- Go言語にはポインタがあるが、不正なメモリアクセスができないようにポイント演算ができない
- 型のチェックが厳密
継承がない
- クラスがない
- 変わりに「埋め込み」・「インタフェース」がある
エラーハンドリングが容易
- try〜catchで囲うような事が不要
- 必要なところでエラーハンドリングの記述をすればよい
開発環境について
コンパイラ
gc あるいは GCC
プログラムファイル拡張子
.go
インストール(MacOSX)
brew install go
バージョン確認
% go version
go version go1.11.2 darwin/amd64
コマンドによる直接実行
go run {プログラムファイル名}
実行ファイルを生成する
go build {プログラムファイル名}
コメントアウトの方法
単一
// 単一行コメントアウト
複数行
/*複数行
コメントアウト
*/
goコマンド確認
go help
Go is a tool for managing Go source code.
Usage:
go <command> [arguments]
The commands are:
bug start a bug report
build compile packages and dependencies
clean remove object files and cached files
doc show documentation for package or symbol
env print Go environment information
fix update packages to use new APIs
fmt gofmt (reformat) package sources
generate generate Go files by processing source
get download and install packages and dependencies
install compile and install packages and dependencies
list list packages or modules
mod module maintenance
run compile and run Go program
test test packages
tool run specified go tool
version print Go version
vet report likely mistakes in packages
Use "go help <command>" for more information about a command.
Additional help topics:
buildmode build modes
c calling between Go and C
cache build and test caching
environment environment variables
filetype file types
go.mod the go.mod file
gopath GOPATH environment variable
gopath-get legacy GOPATH go get
goproxy module proxy protocol
importpath import path syntax
modules modules, module versions, and more
module-get module-aware go get
packages package lists and patterns
testflag testing flags
testfunc testing functions
Use "go help <topic>" for more information about that topic.
go bug
bugレポート機能
以下コマンドを実行すると、Go言語に対するGithubのissue発行画面が表示されます。
go bug
go clean
buildした結果の実行ファイル等がclearされる。
以下実行イメージ
% ls
hello.go hello
% go build hello.go
% ls
hello hello.go
% go clean hello.go
% ls
hello.go
%
go doc
godoc対応用にコメントを記載しておくことで、コメントを参考にテキストが出力される
go doc 実行フォルダには、以下のコードを格納している。
https://qiita.com/ynarasak/items/10a903366e697b67a20c#helloworld%E3%81%A7%E8%80%83%E5%AF%9F
% go doc
これはGo言語テスト用プログラム
package main
runしたい場合にはmainパッケージを定義して func mainを定義するのが必須
go env
Go内の環境変数確認ができます
% go env
GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/xxxxx/Library/Caches/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/xxxxx/go"
GOPROXY=""
GORACE=""
GOROOT="/usr/local/Cellar/go/1.11.2/libexec"
GOTMPDIR=""
GOTOOLDIR="/usr/local/Cellar/go/1.11.2/libexec/pkg/tool/darwin_amd64"
GCCGO="gccgo"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/kl/_97x1fqx5_3_j1wrylh6x2cm0000gp/T/go-build664765921=/tmp/go-build -gno-record-gcc-switches -fno-common"
go fix
指定されたパッケージについてインポートパスを軸に更新される
更新された新しいパッケージが正常に読み込まれない場合とかに使うっぽい
# fmtパッケージを指定した場合
go fix fmt
go fmt
フォーマッター
空白インデントがタブに置き換わり、波括弧の前に空白が入ったり、packageとimportの間に改行入ったりと、適切に空白・改行・タブを入れてくれる
go fmt hello.go
####適用前
package main
import "fmt"
func main(){
// Println は JavaのSystem.out.printlnに酷似している。ダブルクォーテーションではなくシングルにするとエラー
fmt.Println("Hello, World!") //test
}
####適用後
package main
import "fmt"
//func -> function の意味となるが、functionって記載するとエラーになります
func main() {
// Println は JavaのSystem.out.printlnに酷似している。ダブルクォーテーションではなくシングルにするとエラー
fmt.Println("Hello, World!") //test
}
go get
指定されたパッケージがGOPATHに展開され、ビルドもしてくれる。
PATHをきちんと通しておけばそのままパッケージとして利用できるようになります。
# この例は、stringer パッケージをgetしてきた例です
% go env | grep GOPATH
9:GOPATH="/Users/xxxxx/go"
% ls -trl /Users/xxxxx/go ls: /Users/xxxxx/go: No such file or directory
% go get golang.org/x/tools/cmd/stringer
% ls -trl /Users/xxxxx/go
total 0
drwxr-xr-x 3 xxxxx staff 102 Nov 14 15:05 src
drwxr-xr-x 3 xxxxx staff 102 Nov 14 15:05 bin
%
# GOPATHを環境変数にセットする
% unset GOPATH | exp_path=`go env | egrep "GOPATH=" | sed -e 's/"//g'` | export $exp_path
# GOPATH/binをPATHへセットする
% export PATH=$PATH:$GOPATH/bin
# stringer が利用できる
% stringer
Usage of stringer:
stringer [flags] -type T [directory]
stringer [flags] -type T files... # Must be a single package
For more information, see:
http://godoc.org/golang.org/x/tools/cmd/stringer
Flags:
-linecomment
use line comment text as printed text when present
-output string
output file name; default srcdir/<type>_string.go
-tags string
comma-separated list of build tags to apply
-trimprefix prefix
trim the prefix from the generated constant names
-type string
comma-separated list of type names; must be set
go generate
ソースコードの中に //go:generate {実行したいコマンド}
と記載すると、実行したいコマンドが実行される
以下のようなコードを書いて
package generate
//go:generate echo "echo generate!!!!!"
func gen(){
}
実行すると以下のようになる
% go generate generate.go
echo generate!!!!!
%
これだと正直何が嬉しいのか?となるが、先ほどgo get
で取得したstringer
を用いると
ありがたみがわかる。
stringerを記載したgoのコード
package painkiller
type Pill int
//go:generate stringer -type=Pill
const (
Placebo Pill = iota
Aspirin
Ibuprofen
Paracetamol
Acetaminophen = Paracetamol
)
go generate実行
go generate painkiller.go
以下のように、pill_string.so というファイルが生成される
% ls
painkiller.go pill_string.go
自動生成されたコードの内容
// Code generated by "stringer -type=Pill"; DO NOT EDIT.
package painkiller
import "strconv"
const _Pill_name = "PlaceboAspirinIbuprofenParacetamol"
var _Pill_index = [...]uint8{0, 7, 14, 23, 34}
func (i Pill) String() string {
if i < 0 || i >= Pill(len(_Pill_index)-1) {
return "Pill(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _Pill_name[_Pill_index[i]:_Pill_index[i+1]]
}
go install
GOPATHに格納されているmainが格納されているパッケージ名(ディレクトリ名)をパラメータに指定すると
GOPATH/binにbuildした実行ファイルがinstallされる。
自作のhello.goをGOPATHに格納してgo installしてみた結果
% go clean hello.go
% mkdir $GOPATH/src/hello
% mv hello.go $GOPATH/src/hello
% go install hello
% ls $GOPATH/bin/
hello stringer
% hello
Hello, World!
go vet
コードの静的解析を行う。mainのようなファイルではなく個別パッケージをチェックする際に
効果的にコードチェックをするための用途として利用できそう。
例:hello.go
のimport "fmt"
をimport fmt
に変更して実行
% go vet hello.go
can't load package: package main:
hello.go:9:11: expected 'STRING', found newline
hello.go:12:1: expected ';', found 'func'
go test
以下のようなコードを準備して
package example
func main(){
}
func Example(param string) int {
if param == "success" {
return 0
}
return 99
}
package example
import "testing"
func TestExampleSuccess(t *testing.T){
result := Example("success")
if result != 0 {
t.Fatal("failed test")
}
}
以下の様なコマンドを実行するとテストされる
% go test
PASS
ok _/Users/xxxxx/Projects/study/go_test/example 0.008s
その他
go list
, go mod
は利用用途がいまいちわかっておらず。宿題
HelloWorldで考察
/*
これはGo言語テスト用プログラム
package main
runしたい場合にはmainパッケージを定義して func mainを定義するのが必須
*/
package main
//import fmt -> fmtという名前のpackageを読み込んでいる。ダブルクォーテーション必須
import "fmt"
//func -> function の意味となるが、functionって記載するとエラーになります
func main() {
// Println は JavaのSystem.out.printlnに酷似している。ダブルクォーテーションではなくシングルにするとエラー
fmt.Println("Hello, World!")
}
package mainでない場合
go run: cannot run non-main package
import "fmt"が存在しない場合
undefined: fmt
import "fmt"
を誤って import fmt
と記載してしまった場合
package main:
expected 'STRING', found newline
expected ';', found 'func'
func mainが存在しない場合
runtime.main_main·f: function main is undeclared in the main package
func main(){
の {
前で改行してしまった場合
以下の様にすると
func main()
{
fmt.println("xxxx")
}
以下の様なエラーになる
missing function body
syntax error: unexpected semicolon or newline before {
GO言語では波括弧の位置が決められており、波括弧の位置で不毛な論争が起こることはないそうw
"Hello, World"
ではなく 'Hello, World'
のようにシングルクォートで囲った場合
invalid character literal (more than one character)
参考