LoginSignup
12
13

More than 5 years have passed since last update.

Go言語入門メモ

Last updated at Posted at 2018-11-14

背景

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 {実行したいコマンド} と記載すると、実行したいコマンドが実行される

以下のようなコードを書いて

generate.go
package generate

//go:generate echo "echo generate!!!!!"

func gen(){

}

実行すると以下のようになる

% go generate generate.go
echo generate!!!!!
%

これだと正直何が嬉しいのか?となるが、先ほどgo getで取得したstringerを用いると
ありがたみがわかる。

stringerを記載したgoのコード

./painkiller/painkiller.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

自動生成されたコードの内容

./painkiller/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.goimport "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

以下のようなコードを準備して

example.go
package example
func main(){
}

func Example(param string) int {
  if param == "success" {
    return 0
  }
  return 99
}
example_test.go
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で考察

hello.go
/*
 これは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)

参考

12
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
13