忘却のgo

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

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

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

```go
	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が返ります

```go
	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のほうはハッシュマークの面倒を見てくれることしかないように思います。

```go
	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を放り込むと二重にデコードしちゃう形になるので気を付けましょう。
例えば文字列としてプラス記号とか混ざってた場合、空白になってしまって悲しみを背負います。
なお、`netu`は`net/url`に与えてるエイリアスです そのまんまだとurlって変数名とかぶるんで…

```go
	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として成立してさえいれば彼らは怯まないようです。

```go
	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`のような形式ですね。エラーとはなりませんがあまり喜ばしい結果でもありません。

```go
	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が使えます。

```go
	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の仕様をちゃんと理解しろっつう話なんですが

```go
	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)と思えば良いか。

```go
	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しないんだ…実務上困ることは無さそうだけど謎…