1
1

More than 3 years have passed since last update.

忘却のgo

Last updated at Posted at 2020-06-08

使うたんびに毎回「あれ…」ってなってplaygroundで確認しなおす個人的事項をここに
でもどうせまた次も忘れて確認すんだろうな…

slice操作

https://github.com/golang/go/wiki/SliceTricks
大体ここで困らない

rand.Intn

0..引数で渡した値「未満」の値になります。関数のコメントに0..nって書いてあるからそりゃそうなんですが、..nはn未満で...nはn以下って割と忘れそうになる表現。

    rand.Seed(time.Now().UnixNano())
    for i := 0; i < 10; i++ {
        fmt.Println(rand.Intn(2)) // 0 or 1
    }

空文字をsplit

rubyだと空文字をsplitすると空配列が返りますが、golangは先頭の要素が空文字である1要素のsliceが返ります

    str := ""
    result := strings.Split(str, "@")
    fmt.Println(result) // => []
    fmt.Println(len(result)) // => 1
    if result[0] == "" {
        fmt.Println("yes empty") // 出力される
    }

HTTP/HTTPS URLパース関連

ParseとParseRequestURI

実装見ればすぐですが、両方ともparseって関数でバラすことには変わりありません。
違いはParseのほうはハッシュマークの面倒を見てくれることしかないように思います。

    url := `http://test.com/path#hashmark`

    parsed, _ := netu.ParseRequestURI(url)
    fmt.Println(parsed.Fragment) // => empty

    parsed, _ = netu.Parse(url)
    fmt.Println(parsed.Fragment) // => hashmark

デコード

net/urlパッケージのParse/ParseRequestURI共に、デコードまで面倒見てくれます。
QueryUnescapeを通したあとのURLを放り込むと二重にデコードしちゃう形になるので気を付けましょう。
例えば文字列としてプラス記号とか混ざってた場合、空白になってしまって悲しみを背負います。
なお、netunet/urlに与えてるエイリアスです そのまんまだとurlって変数名とかぶるんで…

    url := `http://test.com?param=%E3%81%82%E3%81%82%2B%E3%81%82`

    parsed, err := netu.ParseRequestURI(url)
    fmt.Println(err)            // => nil
    fmt.Println(parsed.Query()) // => map[param:[ああ+あ]]

    decoded, err := netu.QueryUnescape(url)
    fmt.Println(err)
    parsed, _ = netu.ParseRequestURI(decoded)
    fmt.Println(parsed.Query()) // => map[param:[ああ あ]] 二重にデコードされる

QueryUnescapeに失敗するパラメータが含まれているURLをパースしようとした場合

爽やかに通ります。基本的にURLとして成立してさえいれば彼らは怯まないようです。

    url := `http://test.com/?param=%%%&a=b`

    parsed, err := netu.ParseRequestURI(url)
    fmt.Println(err)            // => nil
    fmt.Println(parsed.Path)    // => /
    fmt.Println(parsed.Host)    // => test.com
    fmt.Println(parsed.Query()) // => map[a:[b]]

    _, err = netu.QueryUnescape(url)
    fmt.Println(err) // => invalid URL escape "%%%"

Schemaが省略されている場合

//aaa.comのような形式ですね。エラーとはなりませんがあまり喜ばしい結果でもありません。

    url := `//test.com/?param=%E3%81%82%E3%81%82%2B%E3%81%82`

    parsed, err := netu.ParseRequestURI(url)
    fmt.Println(err)            // => nil)
    fmt.Println(parsed.Path)    // => //test.com/
    fmt.Println(parsed.Host)    // => empty
    fmt.Println(parsed.Query()) // => map[param:[ああ+あ]]

    decoded, err := netu.QueryUnescape(url)
    fmt.Println(decoded) // => //test.com/?param=ああ+あ
    fmt.Println(err)     // => nil

ちょっとアレですが、パースしてSchemaが空だったら勝手に補完してもう1回パースする、とかでお茶を濁してます。

文字列置換

regexpで無くてもなんとかなる単純な置換だが、置換候補が複数あるような場合、strings.Replaceを連発するのはちょっとねって時にはstrings.NewReplacerが使えます。

    str := "yesNOyeahBAR"
    rep := strings.NewReplacer("yes", "NO", "yeah", "BAR")
    a := rep.Replace(str)
    fmt.Println(a) // => NONOBARBAR

    str = "yesNOyeahBAR"
    rep = strings.NewReplacer("yes", "NO", "yeah", "BAR", "NO", "AHHH")
    a = rep.Replace(str)
    fmt.Println(a) // => NOAHHHBARBAR

下は「まさか単純に左から順番に解決してるんじゃなかろうな…」って一瞬思ってしまったので念のために確認してるやつです。
うっかり無限ループとか流石に笑えない

部分配列

sliceの仕様をちゃんと理解しろっつう話なんですが

    a := []int64{1, 2, 3}
    fmt.Println(a[0:]) // => [1 2 3]
    fmt.Println(a[:]) // => [1 2 3]
    fmt.Println(a[:3]) // => [1 2 3]
    fmt.Println(a[0:3]) // => [1 2 3]
    fmt.Println(a[1:2]) // => [2]
    fmt.Println(a[0:0]) // => []

これはまあ問題ないと思います。
n:aで、nを省略すれば0、aを省略すればlen
nは始点indexを表し、始点そのものも要素に含む
aは始点からの個数
と考えればまあ特に矛盾はしないように思います。が、

コメ指摘があったんで確認しなおしたらaは個数ではないですね。
1...len(index+1)と思えば良いか。

    a := []int64{1, 2, 3}
    fmt.Println(a[3:3]) // => [] ???
    fmt.Println(a[4:]) // => panic
    fmt.Println(a[3:4]) // => panic
    fmt.Println(a[3]) // => panic

なんで1番上がpanicしないんだ…実務上困ることは無さそうだけど謎…

1
1
1

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
1
1