[Golang]sliceの挙動を確認した

ざっくりスライスの挙動を確認。

ポイントは、
– 配列とは別物(値だし)
– 参照型
– 可変長

package main

import (
    "fmt"
)
/*
参照型 は 3種類
1. slice
2. map
3. channel

ここではslice
*/
func main() {

    // int型のslice
    // var s []int // 宣言
    s := make([]int, 10)

    // 配列と似ているが、型として別物
    fmt.Println(s)
    fmt.Println(len(s))

    s2 := make([]int, 5, 10)
    fmt.Println(s2)
    fmt.Println(len(s2))
    fmt.Println(cap(s2))

    // makeを使用しないスライスの生成方法
    s3 := []int{1,2,3,4,5}
    fmt.Println(s3)
    fmt.Println(len(s3))
    fmt.Println(cap(s3))

    // 簡易スライス式
    a := [5]int{1,2,3,4,5}
    s4 := a[0:2]
    fmt.Println(s4)

    s4 = append(s4, 5)
    fmt.Println(s4)
    fmt.Println(a)

    // スライスと可変長引数
    fmt.Println(sum(1,2,3,4))
    fmt.Println(sum(1,2,3,4,6,7,8,98))
}


// 可変長引数サンプル
// 可変長引数は引数の末尾に一つだけ定義できる
func sum(s ...int) int {
    n := 0
    for _,v := range s {
        n += v
    }
    return n
}

ソースはこちら

[Golang]rangeについて

  • rangeは複数の要素を保持する性質を備えるデータ型に使える
  • 配列型で使うのがイメージ湧きやすいが、string型でも使える。
  • というか、色々使える
package main

import (
    "fmt"
)

func main() {
    fruits := [3]string{"apple", "banana", "grape"}

    for i, s := range fruits {
        // i はindex
        // s は要素
        fmt.Printf("fruits[%d]=%s\n", i, s)
    }

    // rangeは複数の要素を保持する性質を備えるデータ型に使える
    // 文字列型をrangeで使うとrune型で取り出す
    strings := "あいうえお"
    for i, s := range strings{
        fmt.Printf("strings[%d]=%s %#U\n", i, s, s)
    }
}

ソースはこちら

もうちょっと丁寧に調べないと。

iti

[Golang]クロージャの挙動を確認してみた

スターティングgoのソースを写経して確認

package main

import (
    "fmt"
)

func later() func(string) string {
    // 一つ前に与えられた文字列を保存するための変数
    var store string

    // 引数に文字列を取り保存されていた文字列を返す関数を返す
    return func(next string) string {
        s := store
        store = next
        return s
    }
}

func increment() func() int {
    i := 0
    return func() int {
        i += 1
        return i
    }
}

func main () {
    f := later()

    fmt.Println(f("hoge"))
    fmt.Println(f("is"))
    fmt.Println(f("great!"))

    f2 := increment()

    fmt.Println(f2())
    fmt.Println(f2())
    fmt.Println(f2())
    fmt.Println(f2())

    f3 := increment()
    fmt.Println(f3()) // クロージャ間で共有されるわけではないので注意

}

もうちょっと色々自分で書いて見る必要がありそう。
手に馴染んでいない感。

ソースはこちら

iti

[Golang]関数の仕様について

ざっと確認してみたので列挙する

package main

import (
    "fmt"
)

func main() {
    fmt.Println(plus(10,45))

    hello()

    a, b := div(20, 32)
    fmt.Println(a,b)

    // 戻り値の破棄
    a2, _  := div(20, 32)
    fmt.Println(a2)


    fmt.Println(hoge())
    fmt.Println(hoge2())

    fmt.Println(div2(4,3))

    // 無名関数 (クロージャ)
    f := func(x, y int) int { return x + y }
    fmt.Println(f(4,3))
    // 無名関数の型定義の確認
    fmt.Printf("%T\n", f)

    // 関数の代入
    var f_alias = f // f_alias := f でも同じ
    fmt.Printf("%T\n", f_alias)

    // 関数を返す関数
    returnFunc()()

    // 関数を引数に取る関数
    callFunc(returnFunc())
}

// ベーシックな関数定義
func plus(x, y int) int {
    return x + y
}

// 戻りの型定義を省略したらvoidになる
func hello() {
    fmt.Println("hello world")
    return // 戻り値がない場合はあってもなくても
}

// 複数の戻り値
func div(x, y int) (int, int) { // 戻り値の型定義のカッコは省略できない
    a := x + y
    b := x - y

    return a, b
}

/*
  戻り値を表す変数
*/
// 関数内のローカル変数定義の省略
func hoge() (a int) {
    return
}

// hogeと同じ
func hoge2() int {
    var a int
    return a
}


// div()のローカル変数定義を省略してみる
func div2(x, y int) (a, b int) {
    a = x + y
    b = x - y

    return a, b
}


// 関数を返す関数
func returnFunc() func() {
    return func() {
        fmt.Println("I'm a function")
    }
}

// 関数を引数に取る関数
func callFunc(f func()) {
    f()
}

ソースはこちら

[Golang]配列型の代入について

goの配列型の代入の仕様。

要素数と要素の数が同一の変数であれば相互に代入が可能。
注意点は、参照ではなくコピーになること。

サンプル

ar1 := [3]int{1,2,3}
ar2 := [3]int{4,5,6}

ar1 = ar2

fmt.Println(ar1) // == [4,5,6]

ar2[0] = 100

fmt.Println(ar1) // == [4,5,6]
fmt.Println(ar2) // == [10,5,6]

// これはサイズ、型が違うのでコンパイルエラー
//ar1 = [3]string{}

配列の挙動確認したソースはこちら

[Golang]オーバーフローとラップアラウンド

Goではオーバーフローが発生した場合、その演算結果をラップアラウンドする。

オーバーフローとは桁あふれのこと。
ラップアラウンドはオーバーフローした際に最初に戻ること。

サンプル

package main

import (
    "fmt"
    "math"
)

func main () {
    // 最大値の定数
    fmt.Printf("unit 32 max value = %d\n", math.MaxUint32)


    b := byte(255)
    fmt.Println(b)
    fmt.Println(b + 1) // == 0
    fmt.Println(b + byte(255)) // -1したのと同じ
}

ソースはこちら
と言っても上と同じ。

あとで他の言語でも仕様の比較をする。

iti

[Golang]配列の要素の並びを逆順にする

Goの練習がてらやってみた

配列操作を簡単に確認。

package main

import (
    "fmt"
)

/*
 配列を渡すとその順番を逆にして表示する
*/
func main() {
    a := [4]string{
        "yamada", 
        "suzuki",
        "tanaka",
        "satou", // この要素にカンマがないとsyntax errorになる
    }

    fmt.Println(a)

    length := len(a)
    fmt.Println(length)

    // その1
    out_ary := []string{}
    for i := 1; i <= length; i++ {
        out_ary = append(out_ary, a[length -i])
    }

    fmt.Println(out_ary)

    // その2
    out_ary2 := []string{}
    for i := length -1 ; i >= 0; i-- {
        out_ary2 = append(out_ary2, a[i])
    }

    fmt.Println(out_ary2)

}

個人的にはその2のほうが素直に書いた感がある。
うーむ。

ソースはこちら