package main

import(
  "fmt"
  "strings"
  "strconv"
  "sort"
  "io/ioutil"
  "log"
)

// ◆Goでは既定値付き引数は定義できないので通常の関数のみ実装
func GetFileNames(dir string, ext string) []string {
    files, err := ioutil.ReadDir(dir)
    if err != nil { log.Fatal(err) }
    fnames := []string{}
    for _, f := range files {
        if f.Mode().IsRegular() { // 通常のファイルなら
            if ext == "" || strings.HasSuffix(f.Name(), ext) {
                fnames = append(fnames, f.Name())
            }
        }
    }
    return fnames
}

// ◆可変長引数を持つ関数を定義する
func GetSum(nums ...int) int {
    sum := 0
    for _,v := range nums{ sum += v }
    return sum
}

func main(){
    // ◆文字列から"b"の文字が最初に現れる位置(先頭が0)を得る
    a := "orange melon strawberry grape"
    n := strings.Index(a, "b")
    fmt.Printf("%d\n", n)

    // ◆その位置から5文字を切り出す
    // GoはPythonと同じ。スライス演算で切り出す
    b := a[n:n+5]
    // berry
    fmt.Println(b)

    // ◆文字列の一部置き換え。4番目の引数は置き換える回数(-1は全ての該当部を置き換える意)
    fmt.Println(strings.Replace(a, "mel", "lem", -1))

    // ◆数値と文字列をそれぞれ加算、文字列連結する
    // Pythonと同じ。内部データ型が異なる変数は+できない。必ず型変換が必要
    v1 := 10.2
    v2 := "15.3"
    // 25.5 10.215.3 25.5 15.310.2
    // Goの場合、ParseFloat関数のerr戻り値を処理する必要があるから、
    // 他の演算と組み合わせて使うことはできず、文を変える必要がある
    v3,_ := strconv.ParseFloat(v2, 64); v3 += v1
    v4 := fmt.Sprint(v1) + v2
    v5 := v3
    v6 := v2 + fmt.Sprint(v1)
    fmt.Printf("%.1f %s %.1f %s\n", v3, v4, v5, v6)

    // ◆配列の3番目の要素から3個を取り出し、文字列に連結して出力する
    arr := [...]string {"orange", "melon", "strawberry", "grape", "apple", "banana"}
    arrsub := arr[2:2+3]
    // strawberry graph apple
    fmt.Println(strings.Join(arrsub, " "))

    // ◆要素の追加。Goでは配列には追加できないので、スライスにして追加する
    arrb := append(arr[:], "peach")

    // ◆要素の検索。というかGoには共通関数はないのでforループで記述する
    var index int = -1
    for i,v := range arrb {
        if v == "peach" { index = i; break }
    }
    fmt.Printf("index of 'peach' is:%d\n", index)

    //// ◆配列要素を変数に一括代入する構文はGoにはない
    //e1, e2, e3 := arrsub
    //// strawberry graph apple
    //fmt.Printf("%s %s %s\n", e1, e2, e3)

    harr := map[string]int { "orange" : 80, "melon" : 1200, "strawberry" : 350 }
    harr["grape"] = 450
    // ◆mapのキーの存在有無をチェックする
    // yes
    _, found := harr["melon"]
    if found { fmt.Println("yes") } else { fmt.Println("no") }
    // no
    _, found = harr["lemon"]
    if found { fmt.Println("yes") } else { fmt.Println("no") }

    // ◆mapのキー一覧をソートして、キーと値を出力する
    keys := make([]string, 0, len(harr))
    for k := range harr {
        keys = append(keys, k)
    }
    sort.Strings(keys)
    for _, k := range keys {
        fmt.Printf("%s\t%d\n", k, harr[k])
    }

    // ◆Goでは既定値付き引数を持つ関数は定義できないので通常の関数のみ実装
    fmt.Println(strings.Join(GetFileNames(".", ""), " "))
    fmt.Println(strings.Join(GetFileNames(".", ".txt"), " "))

    // ◆可変長引数を持つ関数を定義する
    fmt.Printf("%d\n", GetSum(10,11,12,13))
}