LoginSignup
52
53

More than 5 years have passed since last update.

Go言語入門してつまったアレコレ

Last updated at Posted at 2015-05-06

Tour of Goをさらっと流したあとで、開発してみて詰まったところのまとめです。

多次元配列の初期化したい

型のあとに{}を渡してあげればよいです。
例えば2次元配列の場合は{{1, 0}, {0, 1}}みたいな感じで書けば良いです。

int配列の場合は、{}とすると0で初期化されます。

var matrix [2][2]int = [2][2]int {}
// #=> [[0 0] [0 0]]

matrix2 := [2][2]int {}
// #=> [[0 0] [0 0]]

matrix3 := [3][2]int {{0, 1}, {}, {2, 3}}
// #=> [[0 1] [0 0] [2 3]]

多次元スライスの場合も同様です。

package main

import "fmt"

func main() {
    var slice1 [][]int = make([][]int, 3)
    fmt.Println(slice1)
    // #=> [[] [] []]

    slice2 := [][]int{{}, {}, {}}
    fmt.Println(slice2)
    // #=> [[] [] []]
}

ファイル分割したい

main.goがどんどん肥大化していって辛い。
そんな時は、パッケージ化をしてファイルを分割します。

パッケージ化

パッケージ化する場合は、パッケージ名でディレクトリを作成し、
その中に切り出したgoファイルを作っていきます。

.── main.go
└── hoge
     └── fuga.go

packageはhogeになる

hoge/fuga.go
package hoge

import "fmt"

func PrintName() {
        fmt.Println("hoge.fuga")
}

パッケージ化したものはimportで読み込むと、
パッケージ名のプレフィクスをつけて関数などが呼び出せるようになります。
import "../piyo"みたいなこともできます。

main.go
package main

import "./hoge"

func main() {
        hoge.PrintName()
}

関数や構造体をパッケージ外から呼び出したい

名前の先頭を大文字にする(エクスポート)とパッケージ外から呼び出せます。
先程のものに少し手を加えます。

hoge/fuga.go
package hoge

import "fmt"

// 同一パッケージ内からは呼べる
func printName() {
        fmt.Println("hoge.fuga")
}

// 他のパッケージからも呼べる
func PrintName() {
        fmt.Println("hoge.fuga")
}
main.go
package main

import "./hoge"

func main() {
        //hoge.printName()
        // #=> cannot refer to unexported name hoge.printName
        hoge.PrintName()
}

intをstringにしたい

10進数で文字列型に変換したい場合は、strconv.Itoa(i int)を使います。

main.go
package main

import (
"fmt"
"strconv"
)

func main() {
    i := 0
    fmt.Println("int: " + string(i))
    // #=> int: 
    fmt.Println("int: " + strconv.Itoa(i))
    // #=> int: 0
}

for文における変数のスコープ(シャドーイング)

for文で同一の変数を使いまわしたい場合にやってしまったミスです。
:=を使うとfor文のスコープ内で同じ名前で別の変数を再定義することになります。

main.go
package main

import (
        "fmt"
        "strconv"
)

func main() {
        count := 0
        list := []string{}

        // `:=`ではlistが更新されない
        for count < 2 {
                list := append(list, strconv.Itoa(count))
                count += 1
                fmt.Println(list)
        }
        // #=> [0]
        //     [1]

        count = 0
        list = []string{}

        // `=`でlistが更新される
        for count < 2 {
                list = append(list, strconv.Itoa(count))
                count += 1
                fmt.Println(list)
        }
        // #=> [0]
        //     [0 1]
}

標準入力から対話的に1行ずつ読みたい

コマンドラインで実行して、標準入力から1行ずつ読み込みたい場合は、bufio.NewReaderを使います。
対話処理をしたい場合は、関数にして必要なときに呼び出せばよさそうです。

package main

import (
        "bufio"
        "fmt"
        "os"
)

func main() {
        fmt.Print("Please type something\ngo> ")
        reader := bufio.NewReader(os.Stdin)
        line, _, err := reader.ReadLine()
        if err != nil {
                fmt.Println(err)
                os.Exit(1)
        }
        fmt.Println(string(line))
}

mapのキーをソート順で表示したい

map[int]Tみたいなmapにfor rangeを使った場合、取得できるkeyの順序制約はありません。
そのためfmt.Printしてみたら実行毎に順番が変わります。

ちゃんとkeyをソートして使いたい場合は、
keyを取り出してソートしたものをfor rangeで回してあげると順番通り出力できます。

main.go
package main

import (
    "fmt"
    "sort"
)

func main() {
    m := map[int]int{
        3: 0,
        1: 0,
        2: 0,
    }

    // keyの順番で出力されない
    for k, v := range m {
        fmt.Printf("|%v: %v|", k, v)
    }
    // #=> |3: 0||1: 0||2: 0|

    fmt.Println()

    // mapのkeyをスライスで取得してソートし、
    // rangeでループさせて順番に取得する
    var keys []int
    for k := range m {
        keys = append(keys, k)
    }
    sort.Ints(keys)

    // To perform the opertion you want
    for _, k := range keys {
        fmt.Printf("|%v: %v|", k, m[k])
    }
    // #=> |1: 0||2: 0||3: 0|
}

その他

開発中にちょっと関数を試してみたいときはGo Playgroundを使うのが便利でした。

参考

Go言語のスライスを理解しよう
シュッと golang に入門する話
Go でファイルを1行ずつ読み込む(csv ファイルも)
Go 1 Release Notes: Returns and shadowed variables
Golangでの文字列・数値変換
[Go] 構造体の初期化方法まとめ
The Go Blog: Iteration order

52
53
0

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
52
53