それが僕には楽しかったんです。

僕と MySQL と時々 MariaDB

PHPerがいくGolang入門 A Tour of Go More types: structs, slices, and maps

はじめに

どうも、年末にアドカレを1日分書き忘れていたので急いで書き始めたけんつです。
今回も例によって全くPHPは関係無いですが、A Tour of Go の続きをやっていこうかなと思います。

Pointer

きたよ、ポインタが。こいつが来ると謎の安心感がある。
宣言、アドレスの参照などは大体Cと同じ。

package main;

import "fmt";

func main() {
    var number int = 12345;
    var pointer *int = &number;

    fmt.Println(pointer);
    fmt.Println(*pointer);
}

Structs

構造体、ここまでくるとCと大体変わらなくなってくる。
構造体そのものもそうだし、構造体をポインタを通して操作することができる。

package main;

import "fmt";

type Vertex struct {
    X int
    Y int
}

func main() {
    var v Vertex = Vertex{1, 2};
    var p *Vertex = &v;

    fmt.Println(v);

    p.X = 3;

    fmt.Println(v);
}
$ go run structs.go 
{1 2}
{3 2}

こんな感じで。さらに Name: のようにフィールドの一部だけを列挙することができる。

Arrays

配列ですよ、こいつがあればなんとか競プロで戦えそう。

package main;

import "fmt";

func main() {
    var primes [5]int;
    primes[0] = 2;
    primes[1] = 3;
    primes[2] = 5;
    primes[3] = 7;
    primes[4] = 11;

    fmt.Println(primes);

    numbers := [2]string{"hello", "world"};

   fmt.Println(numbers);
}

型の明示的宣言に未だに違和感があるがなんとか。

Slice

これ、Pythonのスライスと似たようなことをやっている印象あるんだけど無駄に長いので結構大変だった。
スライスは配列は固定長なのにたいして可変長のやつをさす
使い方はPythonのそれと基本的には同じ。

package main;

import "fmt";

func main() {
    primes := [6]int{2, 3, 5, 7, 11, 13};

    var slice []int = primes[1:3];
    fmt.Println(slice);
}

また、スライスは配列の部分列に対する参照を指しているので元となる配列の値を変更するとスライス先もその変更が反映されてしまう。

スライスは次のようにするとその配列を参照するスライスを作ることができる。

slices := []int{2,3,5,7,11,13}

これは右端の配列に対するスライスが生成される

さらに、組み込み関数のひとつであるmake関数を使用することによっても背製することができる。

a := make([]int, 5)

スライスは可変と言ったが、すでにあるスライスに対して要素を追加する場合はappend関数を使う。

Range

for などで range を使用する場合スライスやマップに対してひとつずつ反復処理をする場合につかう

package main;

import "fmt";

func main() {
    var pow = []int{1, 2, 4, 8, 16};

    for i, v := range pow {
        fmt.Printf("2**%d = %d\n", i, v);
    }
}

Map

mapが使えるみたいなんだが、割と難解な気がする
なぜここでmake関数を使っているのだろうか…

package main

import "fmt"

type Vertex struct {
	Lat, Long float64
}

var m map[string]Vertex

func main() {
	m = make(map[string]Vertex)
	m["Bell Labs"] = Vertex{
		40.68433, -74.39967,
	}
	fmt.Println(m["Bell Labs"])
	fmt.Println(m)
}

function values

関数もまた変数であるため、他の変数のように渡すことができる。

package main;

import "fmt";
import "math";

func pow(f func(float64, float64) float64) float64 {
    return f(3, 4);
}

func main() {
    
    hypot := func(x float64, y float64) float64 {
        return math.Pow(x, y);
    };

    fmt.Println(hypot(2, 2));
    fmt.Println(pow(hypot));
}