LoginSignup
4
0

More than 3 years have passed since last update.

A Tour of Go メモ ~Packages, variables, and functions~

Last updated at Posted at 2020-12-06

はじめに

Go の勉強のため、A Tour of Goに取り組んでいる
今回はPackages, variables, and functions章について、学んだことを記していく

まとめ記事はこちら

使えそうなスニペット

※筆者は VSCode を使用

  • スニペットは最初の一文字を入力するだけで予測変換に出てくるので、全部を入力する必要はない
  • また、文字を飛ばしても良い
  • 以下の例でいうと、pmと入力してもpkgmが予測変換に出る

pkgm -> package main
fm -> func main(){ }
func -> func (){ }
fp -> fmt.Println("")
ff -> fmt.Printf("", var)
iferr -> if err != nil { return nil, err}

ページごとの補足

A Tour of Goを進めていく中で、疑問に思ったことをまとめた

Packages

Import する package 名は、Import Path の最後の要素になる

  • Ex: math/rand -> rand

同じ名前のパッケージをインポートしたい場合は、Package Name を指定する
また、Package Name にドット(.)を指定すると、修飾子なしにメソッドにアクセスできる

// Import declaration          Local name of Sin

import   "lib/math"         // math.Sin
import m "lib/math"         // m.Sin
import . "lib/math"         // Sin

Ref. The Go Programming Language Specification

math/randの使い方

math/randはシード値が同じであれば同じ疑似乱数を返すため、実行するたびに値を変更したければSeedメソッドを都度呼ぶ必要がある
また、Seedメソッドの引数にtime.Now().UnixNano()を使うことで、疑似乱数が作りやすくなる。

import (
    "fmt"
    "math/rand"
    "time"
)

func main() {
    fmt.Println(rand.Intn(10)) // 1 固定
    rand.Seed(10)
    fmt.Println(rand.Intn(10)) // 4 固定
    rand.Seed(time.Now().UnixNano())
    fmt.Println(rand.Intn(10)) // 毎回変わる
}

ただ、より安全性の高い乱数を作りたい場合はcrypto/randを使用する

package main

import (
    "crypto/rand"
    "fmt"
    "math/big"
)

func main() {
    n, err := rand.Int(rand.Reader, big.NewInt(10))
    if err != nil {
        fmt.Println(err)
    }
    fmt.Println(n)
}

Ref. Go の math/rand と crypto/rand

Imports

複数importする際は Factored Import Statement で記述する
(Factored は直訳で因数分解、意訳でグループ化らしい)
importに限らず、var, constで複数定義する際も、これを用いる
ちなみに、1 つだけ定義した場合もこのスタイルで書ける模様
(フォーマッタに添削されないということは、割とスタンダードなのだろうか)

import (
    "fmt"
    "math"
)

func main() {
    const (
        x = 1
        y = 2
    )
    var (
        z = math.Pi
    )
    fmt.Println(z)
}

Exported names

大文字の名前はエクスポートされ、小文字はされない

foo.go
package foo

func Test() string {
    return "Success"
}
func test() string {
    return "Failure"
}

const (
    CONSTANT = 1
    constant = 2
)
main.go
package main

import (
    "./foo"
    "fmt"
)

func main() {
    fmt.Println(foo.Test())
    fmt.Println(foo.CONSTANT)

    // Error: cannot refer to unexported name foo.test
    // Error: cannot refer to unexported name foo.constant
    fmt.Println(foo.test())
    fmt.Println(foo.constant)
}

ちなみに、ファイル分割の方法は以下が参考になった
Ref. Go 言語の package の作り方: 長くなったコードを別ファイルに切り出す方法

Functions

C 言語や Java 等とは異なり、変数名 型名の順に記述する
理由はこちら
※和訳は、こちらがわかりやすかった

一言で言えば、「こっちのほうが可読性が良いから」

Multiple results

複数の戻り値を返すことができる
戻り値の一部を使わない場合は、受け取る変数名を_にすれば良い
こうしないとコンパイル時にdeclared but not usedとエラーが出る

package main

import (
    "fmt"
)

func swap(x, y string) (string, string) {
    return y, x
}

func main() {
    a, _ := swap("Hello", "World")
    fmt.Println(a)
}

Basic Types

rune(ルーン) とは

'で定義される文字列であり、Unicode のコードポイントを指す。中身は int32 の alias である
コードポイントについてはこちらが分かりやすい

rune と string の違い

※以下の記事を参考にした

実は、string 型は、値を Byte 配列で格納している
そのため、単純に for 文で回すと以下のようになる

    x := "aあ"
    for i := 0; i < len(x); i++ {
        fmt.Printf("% x", x[i])
  }
  // 61 e3 81 82

    for i := 0; i < len(x); i++ {
        fmt.Printf("% v", x[i])
    }
  // 97 227 129 130

1文字を1文字として扱うには、for range構文を使う必要がある
for range 構文で string を回すと、rune が取れる

    x := "aあ"
    for _, y := range x {
        fmt.Printf("% x", y)
  }
  //  61 3042

    fmt.Println("")
    for _, y := range x {
        fmt.Printf(" %c", y)
    }
  // a あ

%cは整数(コードポイント)に対応する文字を返す
Ref. fmt.Printf なんかこわくない

Zero Values

変数に初期値が与えられないとゼロ値が与えられる
逆に、変数にゼロを与えた場合は、表記によって型が変わる

    fmt.Printf("%T", 0)   // int
    fmt.Printf("%T", 0.0) // float64

蛇足

ルーンって型名を使ってるだけで、Go 言語が大好きになった
以下を忘れないようにしよう
(キャスニキの呪文のコードポイントも調べようとしたけど、長すぎるので断念……)

    ansz := 'ᚨ' // アンサズ: 発火のルーン
    fmt.Printf("%d, %x", ansz, ansz) // 5800, 16a8
4
0
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
4
0