たなしょのメモ

日々勉強していることをつらつらと

7/27 週報

週報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)
}

読書

https://note.com/shosagyo/n/nb1093747c7d3