週報7/27
Go
select
selectを使うことでgoroutineを別々に動かすことができるのか。
便利そう。
package main import ( "fmt" "time" ) func goroutine1(ch chan string) { for { ch <- "packet from 1" time.Sleep(3 * time.Second) } } func goroutine2(ch chan int) { for { ch <- 100 time.Sleep(1 * time.Second) } } func main() { c1 := make(chan string) c2 := make(chan int) go goroutine1(c1) go goroutine2(c2) for { select { case msg1 := <-c1: fmt.Println(msg1) case msg2 := <-c2: fmt.Println(msg2) } } }
ループは指定して抜けることができる
ループは名前をxxx:と記載してbreakで抜けたいときにbreak xxxとすると名前のあるループから抜けることができる。
func main() { tick := time.Tick(100 * time.Millisecond) boom := time.After(500 * time.Millisecond) OuterLoop: for { select { case <-tick: fmt.Println("tick.") case <-boom: fmt.Println("BOOM!") break OuterLoop default: fmt.Println(" .") time.Sleep(50 * time.Millisecond) } } fmt.Println("#######end#######") }
mux
同時に書き込みを実施する際にロックやアンロックを使用して書き込みがぶつかることを防ぐ。
package main import ( "fmt" "sync" "time" ) type Counter struct { v map[string]int mux sync.Mutex } func (c *Counter) Inc(key string) { c.mux.Lock() defer c.mux.Unlock() c.v[key]++ } func (c *Counter) Value(key string) int { c.mux.Lock() defer c.mux.Unlock() return c.v[key] } func main() { c := Counter{v: make(map[string]int)} go func() { for i := 0; i < 10; i++ { c.Inc("Key") } }() go func() { for i := 0; i < 10; i++ { c.Inc("Key") } }() time.Sleep(1 * time.Second) fmt.Println(c, c.Value("key")) }
パッケージ
パッケージを設定するにはGOPATHを設定しなくてはならない。
export $GOPATH=任意のpath
上記で設定できる。
ただしgoは$GOPATH/srcでパッケージを検索しに行くのでディレクトリ構成は気をつける。
package main import ( "fmt" "package/mylib" "package/mylib/under" ) func main() { s := []int{1, 2, 3, 4, 5} fmt.Println(mylib.Average(s)) mylib.Say() under.Hello() }
mylib配下
math.go
package mylib func Average(s []int) int { total := 0 for _, i := range s { total += i } return int(total / len(s)) }
human.go
package mylib import "fmt" func Say() { fmt.Println("Human!") }
under/sub.go
package under import "fmt" func Hello() { fmt.Println("Hello!") }
Publicとprivate
大文字と小文字の違いでpublicとprivateを分ける。
package/mylib配下のhuman.goではPublicとprivateの記載がある。
package mylib import "fmt" var Public string = "Public" var private string = "private" type Person struct { Name string Age int } func Say() { fmt.Println("Human!") }
main.goではfmt.Println(mylib.Public)は表示されるが、
fmt.Println(mylib.private)はエラーが起きる。
package main import ( "fmt" "package/mylib" "package/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) fmt.Println(mylib.Public) fmt.Println(mylib.private) }
test
xxx_test.goとモジュールの名前をつけて、import "testing"をつけることでテストモジュールを作成することができる。
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を打鍵するすること。
ここではmath_test.goのモジュールがあるディレクトリよりも上の階層のディレクトリでコマンドを実行して_test.goモジュールが存在するか確認している。
go test ./...
go test -vで詳細を見ることができる。
go-talib
株のことをみるために使うライブラリらしい。
regexp
正規表現を使われているときにつかうと便利らしい MatchStringは比較の際につからしい。
package main import ( "fmt" "regexp" ) func main() { match, _ := regexp.MatchString("a([a-z]+)e", "apple") fmt.Println(match) }
MustCompileを使うと正規表現の仕方を予め決められるため、matchstringと組み合わせることで色々な単語と比較することができる。
r := regexp.MustCompile("a([a-z]+)e") ms := r.MatchString("apple") fmt.Println(ms)
使い方を応用するとファイル検索なんかにも応用できるかも。
r2 := regexp.MustCompile("^/(edit|save|view)/([a-zA-Z0-9]+)$") fs := r2.FindString("/view/test") fmt.Println(fs) fss := r2.FindStringSubmatch("/view/test") fmt.Println(fss, fss[0], fss[1], fss[2]) fss = r2.FindStringSubmatch("/edit/test") fmt.Println(fss, fss[0], fss[1], fss[2]) fss = r2.FindStringSubmatch("/save/test") fmt.Println(fss, fss[0], fss[1], fss[2])
sort
sortを利用すると色々ソートができる。 int型にはInts、string型にはstringsを使うとソートができる。
package main import ( "fmt" "sort" ) func main() { i := []int{5, 3, 2, 8, 7} s := []string{"d", "a", "f"} p := []struct { Name string Age int }{ {"Nancy", 20}, {"Vera", 40}, {"Mike", 30}, {"Bob", 50}, } fmt.Println(i, s, p) sort.Ints(i) sort.Strings(s) fmt.Println(i, s, p) }