【文法系】【go】基本20:パッケージ

本noteの概要

golang(以下、go)の基本的な文法と出力内容について確認する。

本noteの対象者

・goをインストール済みの方
※ 筆者は仮想環境上でgoを実行していますが、ローカル環境でも基本的に挙動は変わらないと思います、goがインストールされていれば問題ないかと。

▽ 仮想環境上でgoを動かしたい方は以下参考までに ▽
【手順系】【go】仮想環境上でのWebアプリケーション開発①:go環境構築 - This is My note

本noteの環境

PC環境(ホスト)

# OSのバージョン
(base) $ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.14.6
BuildVersion:   18G2022

# Virtualboxのバージョン
(base) $ VBoxManage -v
6.1.2r135662

# vagrantのバージョン
(base) $ vagrant -v
Vagrant 2.2.7

仮想環境(ゲスト)

# Linuxのバージョンが記載されているファイルを検索
vagrant@:~$ ls /etc/*-release
/etc/lsb-release  /etc/os-release

# ゲストOSのバージョンを出力
vagrant@:~$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=16.04
DISTRIB_CODENAME=xenial
DISTRIB_DESCRIPTION="Ubuntu 16.04.6 LTS"

仮想環境上のディレクトリ構成

workspace
  - src
    - test
      - lesson.go

現在のディレクト

vagrant@vagrant-ubuntu-trusty-64:~/workspace/src/myapp$ pwd
/home/vagrant/workspace/src/myapp

【注】
 以降、特段の記述がない限り、コマンドの実行は現在のディレクトリ(test)で行われるものとし、文字数削減のため、表記を以下に省略して記述する。

 省略前:vagrant@vagrant-ubuntu-trusty-64:~/workspace/src/myapp$
  ↓
 省略後:$

Today's Thema:パッケージ

1.

使用例

ディレクトリ構成

.
├── main.go
└── mylib
    └── math.go

<main.go>

package main

import (
    "./mylib"
    "fmt"
)

func main() {
    s := []int{1, 2, 3, 4, 5}
    fmt.Println(mylib.Average(s))
}

<mylib/math.go>

package mylib

func Average(s []int)int{
    total := 0
    for _, i := range s{
        total += i
    }
    return int(total/len(s))
}
▼ 実行
$ go run lesson.go

3

《解説》

使用例

ディレクトリ構成

.
├── main.go
└── mylib
    └── math.go
    └── human.go

<mylib/human.go>

package mylib

import "fmt"

func Say(){
      fmt.Println("Human!")
}
▼ 実行
$ go run lesson.go

3
Human!
⑶ さらに下に階層をつくる
使用例

ディレクトリ構成

.
├── main.go
└── mylib
    └── math.go
    └── human.go
    └── under
        └── sub.go

<under/sub.go>

package main

import (
        "fmt"
        "./mylib"
        "./mylib/under"
)

func main() {
    s := []int{1, 2, 3, 4, 5}
        fmt.Println(mylib.Average(s))
     
        mylib.Say()
        under.Hello()
}
▼ 実行
$ go run lesson.go

3
Human!
Hello!
⑷ structをmainから呼び出す
使用例

ディレクトリ構成

.
├── main.go
└── mylib
    └── math.go
    └── human.go
    └── under
        └── sub.go

<mylib/human.go>

package main

import (
        "fmt"

        "./mylib"
        "./mylib/under"
)

func main() {
    s := []int{1, 2, 3, 4, 5}
        fmt.Println(mylib.Average(s))
     
        mylib.Say()
        under.Hello()
        person := mylib.Person{Name: "Mike", Age: 20}
        fmt.Println(person)
}

<main.go>

package main

import (
        "fmt"

        "./mylib"
        "./mylib/under"
)

func main() {
    s := []int{1, 2, 3, 4, 5}
        fmt.Println(mylib.Average(s))
     
        mylib.Say()
        under.Hello()
        person := mylib.Person{Name: "Mike", Age: 20}
        fmt.Println(person)
}
▼ 実行
$ go run lesson.go

3
Human!
Hello!
{Mike 20}

《解説》
structの変数を小文字で書くと、同一パッケージからはアクセスできるが、別のパッケージ(今回であればmain)からはアクセスできなくなってしまうため注意。

<mylib/human.go>

package mylib

import "fmt"

type person struct{ // 小文字に
    name string // 小文字に
    age int // 小文字に
}

func Say(){
      fmt.Println("Human!")
}

<main.go>

package main

import (
        "fmt"

        "./mylib"
        "./mylib/under"
)

func main() {
    s := []int{1, 2, 3, 4, 5}
        fmt.Println(mylib.Average(s))
     
        mylib.Say()
        under.Hello()
        person := mylib.person{name: "Mike", age: 20} // 小文字に
        fmt.Println(person)
}
▼ 出力
# command-line-arguments
./main.go:16:13: cannot refer to unexported name mylib.person
./main.go:16:13: undefined: mylib.person
⑸ testing
単体テスト

テストをしたいプログラム(goファイル)と同階層に「テストをしたいgoファイルの名前_test.go」というファイルを作成する

ディレクトリ構成

.
├── main.go
└── mylib
    └── math.go
    └── math_test.go // 追加
    └── human.go
    └── under
        └── sub.go

<mylib/math_test.go>

package mylib

import "testing"

func TestAverage(t *testing.T) {
    v := Average([]int{1, 2, 3, 4, 5})
    if v != 3{
        t.Error("Expected 3, got", v)
    }
}
▼ 実行
$ go test ./...

?       _/home/vagrant/workspace/src/myapp  [no test files]
ok      _/home/vagrant/workspace/src/myapp/mylib    0.003s
?       _/home/vagrant/workspace/src/myapp/mylib/under  [no test files]

$ go test -v ./...

?       _/home/vagrant/workspace/src/myapp  [no test files]
=== RUN   TestAverage
--- PASS: TestAverage (0.00s)
PASS
ok      _/home/vagrant/workspace/src/myapp/mylib    0.003s
?       _/home/vagrant/workspace/src/myapp/mylib/under  [no test files]

《解説》
go test ./...コマンドでカレントディレクトリ下にあるテストファイルを探して実行。テストファイルがない場合には「[no test files]」を返す。
go test -v ./...コマンドはテスト内容の詳細表示。
goには基本的なテストしかないため、しっかりとしたテストを実行したい場合などは、Ginkgoなどがおすすめ。

https://qiita.com/SYZ/items/373b1150f3f060103730

⑹ gofmt(goフォーマット)

gofmtを使用すると、goの書き方に合わせてコードを修正してくれる。

①:gofmt goファイル名

指定したファイルの中身をgoの書き方に修正してターミナルに出力。

<mylib/math.go>

package mylib




func Average(s      []int)int      {
    total := 0
    for _, i :=     range s{
        total += i
    }
    return int(total      /len(s      ))
}
▼ 実行
mylib$ gofmt math.go

package mylib

func Average(s []int) int {
    total := 0
    for _, i := range s {
        total += i
    }
    return int(total / len(s))
}

《解説》

②:gofmt -w goファイル名

指定したファイルの中身をgoの書き方に合わせて修正し、ファイルの中身自体を書き換えてくれる。

<mylib/math.go>

package mylib




func Average(s      []int)int      {
    total := 0
    for _, i :=     range s{
        total += i
    }
    return int(total      /len(s      ))
}
▼ 実行
mylib$ gofmt -w math.go

<mylib/math.go>

package mylib

func Average(s []int) int {
    total := 0
    for _, i := range s {
        total += i
    }
    return int(total / len(s))
}

《解説》

サードパーティーのパッケージのインストール

$ go get インストールするパッケージ
今回インストールするパッケージ
GitHub - markcheno/go-talib: A pure Go port of TA-Lib (http://ta-lib.org)

その他のサードパーティーパッケージは以下参照
GoDoc

パッケージのインストール

$ go get github.com/markcheno/go-talib

goのパッケージがインストールされている場所の確認

$ go env | grep GOPATH
GOPATH="/home/vagrant/go"

インストールしたパッケージの確認

$ cd /home/vagrant/go
go$ ls
pkg  src

go$ cd src/
go/src$ ls
github.com

go/src$ cd github.com
go/src/github.com$ ls
markcheno

パッケージのインストール

$ go get github.com/markcheno/go-quote

コードの記載 インストールしたパッケージのGithubにあるExampleをそのまま記載。
<main.go>

package main

import (
    "fmt"
    "github.com/markcheno/go-quote"
    "github.com/markcheno/go-talib"
)

func main() {
    spy, _ := quote.NewQuoteFromYahoo("spy", "2016-01-01", "2016-04-01", quote.Daily, true)
    fmt.Print(spy.CSV())
    rsi2 := talib.Rsi(spy.Close, 2)
    fmt.Println(rsi2)
}

main.goがあるディレクトリに戻って以下を実行

▼ 実行
$ go run main.go

datetime,open,high,low,close,volume
2016-01-04 00:00,200.49,201.03,198.59,185.92,222353500.00
2016-01-05 00:00,201.40,201.90,200.05,186.24,110845800.00
2016-01-06 00:00,198.34,200.06,197.60,183.89,152112600.00
2016-01-07 00:00,195.33,197.44,193.59,179.48,213436100.00
2016-01-08 00:00,195.19,195.85,191.58,177.51,209817200.00
2016-01-11 00:00,193.01,193.41,189.82,177.68,187941300.00
2016-01-12 00:00,193.82,194.55,191.14,179.11,172330500.00
2016-01-13 00:00,194.45,194.86,188.38,174.65,221168900.00
2016-01-14 00:00,189.55,193.26,187.66,177.51,240795600.00
2016-01-15 00:00,186.77,188.76,185.52,173.70,324846400.00
2016-01-19 00:00,189.96,190.11,186.20,173.94,195244400.00
2016-01-20 00:00,185.03,187.50,181.02,171.71,286547800.00
2016-01-21 00:00,186.21,188.87,184.64,172.67,195772900.00
2016-01-22 00:00,189.78,190.76,188.88,176.21,168319600.00
2016-01-25 00:00,189.92,190.15,187.41,173.55,130371700.00
2016-01-26 00:00,188.42,190.53,188.02,175.91,141036800.00
2016-01-27 00:00,189.58,191.56,187.06,174.00,185681700.00
2016-01-28 00:00,189.96,190.20,187.16,174.91,143798800.00
2016-01-29 00:00,190.02,193.88,189.88,179.17,210529300.00
2016-02-01 00:00,192.53,194.58,191.84,179.11,136061600.00
2016-02-02 00:00,191.96,191.97,189.54,175.88,182564900.00

〜中略〜

[0 0 11.805138424204099 2.737417921772375 1.6236355292365552 8.280483916125652 56.41181226441782 13.210013791344194 56.23373812144925 24.262958081960942 29.151499083088687 12.98848538074747 41.15032016304844 82.60831803149993 40.11137682547193 68.71920147811743 38.769619274868674 56.65640833450013 88.43649560302671 86.50927232770997 27.27345009263249 49.75170865128946 56.781626138262695 12.891615447548046 6.223179254179022 6.606276618939291 5.844427039641772 1.3065838466637951 71.21984520208864 86.82078611920139 93.62385848231581 74.12207060089115 70.76443355887687 92.30467860170151 40.06362037915057 57.33776517520462 83.15578831123342 67.45567533286915 29.534847273534464 83.77699194472726 87.53180346410304 91.13000160360744 94.0107627029488 94.83644854861915 19.866664331860793 53.070147719517315 58.662246515518866 92.86882220427496 81.92004797782417 63.05407838123072 85.96912267237236 94.073858999178 96.55488432539273 97.35709326625738 82.74114996190607 17.661516166180068 15.984625049680359 32.956170574310484 90.85195137929757 94.99230492260554 63.207998184389005]

《解説》

【補足】
以下のようにすることで、importしたパッケージの名前を変更することもできる。

package main

import (
    "fmt"
    "github.com/markcheno/go-quote"
    a"github.com/markcheno/go-talib" // パッケージ名の前に任意の名前を設定(今回はa)
)

func main() {
    spy, _ := quote.NewQuoteFromYahoo("spy", "2016-01-01", "2016-04-01", quote.Daily, true)
    fmt.Print(spy.CSV())
    rsi2 := a.Rsi(spy.Close, 2) // デフォルトのtalibを今回設定したパッケージ名(a)に変更
    fmt.Println(rsi2)
}

また、コード内で使用しないパッケージは以下のようにアンダースコアをつけることで、エラーが発生しないようにすることもできる。

package main

import (
    "fmt"
    "github.com/markcheno/go-quote"
    _ "github.com/markcheno/go-talib"
)

func main() {
    spy, _ := quote.NewQuoteFromYahoo("spy", "2016-01-01", "2016-04-01", quote.Daily, true)
    fmt.Print(spy.CSV())
    // rsi2 := talib.Rsi(spy.Close, 2)
    fmt.Println(rsi2)
}

今後はgo getではなく、vgoを使用することが多くなるかも、、?
vgo - GoDoc