いまさら聞けないGo言語

More than 3 years have passed since last update.


Go言語とは

Googleによって開発されているプログラミング言語。実行速度・コンパイル速度が早く、並列処理の記述が容易なことなどが特徴。C言語の置き換え目的をやや意図して作られている感がある。


特徴


  • コンパイル速度は早い。早くするために冗長な記述を極力減らして言語自体をスリム化しているらしい


hello.go

package main

import "fmt"

func main() {
fmt.Println("Hello, Golang!")
}


$ go build hello.go

$ ./hello
Hello, Golang!


  • インタプリタなイメージでバイナリ作らずに実行も出来る

$ go run hello.go

Hello, Golang!


  • コンパイルチェックが非常に厳しい。使ってない変数などあるとコンパイル失敗


compile_error.go

package main

func main() {
var value int
}


$ go build compile_error.go

# command-line-arguments
./compile_error.go:4: value declared and not used


  • コーディングルールが言語で規定されており、整形できる


    • アバウトに実装しておいて後から整形すれば良いので属人性は出ない



$ go fmt compile_error.go

compile_error.go


  • クロスコンパイルが容易。言語標準で各種プラットフォーム(os: linux/darwin/windows, arch: amd64/386/arm 他、iOS/Androidもあるらしい)が用意されている


クロスコンパイル環境用意

$ cd $GOROOT/src

$ GOOS=windows GOARCH=amd64 ./make.bash


クロスコンパイル

$ GOOS=windows GOARCH=amd64 go build hello.go  #hello.exe がビルドされる



  • Goライブラリは全てソースから取り込んで内包でビルドする


info.go

package main

import (
"fmt"
"github.com/toshi3221/theta_v2" // https://github.com/toshi3221/theta_v2 ライブラリ
"os"
)

func main() {
...
client, _ := theta_v2.NewClient(host)


ライブラリは$GOPATH/src以下に取り込むパスで置かれる。ライブラリの取得はGitかMercurialに対応しているURLからとる

$ go get https://github.com/toshi3221/theta_v2  # $GOPATH/src/github.com/toshi3221/theta_v2にgit cloneされる


  • 標準ライブラリがまあまあ充実している。WebAPIクライアントとかなら完結しそうなくらいにはある

Packages - The Go Programming Language

json / xml / net / net/http / database etc...


  • クラス・継承などがない。構造体にメソッド定義。JSのprototypeに似ている?


    • 可視性は大文字キャプションでpublic、小文字キャプションでprivateになる。



type Client struct {

Url string
httpClient http.Client
Response *http.Response
}

func (client *Client) Info() (info Info, error error) {


  • インターフェースはある。メソッド定義のみ

type Container interface {

Begin() Iterator
End() Iterator
}


  • 例外処理を推奨していない(一応panic関数というはある)。エラーはちゃんと関数で結果として返してハンドリングしなさいという考え方

errorインターフェースが標準で用意されているのでこれに沿ってレスポンスを返すことが推奨されている

type error interface {

Error() string
}

// responseとerrorの2つを返している。Go言語は値を代入すればリターン可能

func (client *Client) CheckForUpdates(stateFingerprint string, waitTimeout *int) (response CheckForUpdatesResponse, error error) {
...
client.Response, error = client.httpClient.Post(client.Url+"/osc/checkForUpdates", "application/json", strings.NewReader(request_json))
if error != nil {
return
}
...
return
}

// := は型推論で変数定義して代入するという意味

response, error := client.CheckForUpdatesclient.CheckForUpdates(fingerprint, nil)
// ・・・エラーハンドリングしないときは省略も出来る
response, _ := client.CheckForUpdatesclient.CheckForUpdates(fingerprint, nil)


  • 安全なポインタ


    • *でポインタ、&でアドレス参照が行える。

    • Go言語ではポインタ渡ししない場合は関数の引数や返値で全てコピーされるので注意

    • ポインタ演算は出来ない。同じ変数アドレスを扱うことだけ出来、安全性が高い



var 変数名 * = &変数


  • 並列プログラミングが容易


    • 1.4以前は1スレッドを内部でタスク分割する擬似的な並行処理(環境変数で実験的には複数可能)だったが、1.5からCPU core数分同時処理が行えるようになった

    • go 関数呼び出しで呼べる

    • 同期したい場合はチャネルを使うが割愛



func main() {

...
go func() {
// 並列処理したいプログラム
}()
...
}


所感


  • 軽い・早い・デプロイ楽。Oneバイナリなので余計な環境構築要らないのが良い


    • ただ、ライブラリは内包なのでバイナリサイズは大きくなる。組み込み系で採用するのは別途検討が要る



  • C/C++言語よりは書きやすいと思う。JavaからもGo文法の癖に慣れたならまあ良いのでは無いか。メリット考えると置き換えは十分検討出来る。Perl/Ruby/Python等よりは非常に実装はめんどくさい。そちらでうまくまわっているなら置き換えは要らないと思う。

  • dockerなどミドルウェアで採用されている等大規模開発で実績が増えて来ており、1.5にて標準ライブラリのGo言語による記述整備や並列プログラミングの本格化等、実用化で採用する時期はそろそろ来ているという印象