Help us understand the problem. What is going on with this article?

A Tour of Go memo basics_3 (ポインタ/構造体/配列/map/slices)

More than 1 year has passed since last update.

目次

basics_1 (パッケージ, 変数, 関数)
basics_2 (制御文)
basics_3 (構造体/配列/map/slices)

pointers (ポインタ)

Goでもポインタという概念が使われます。このポインタというものはメモリ番地を直接さし示すものです。
各変数にはポインタが存在し&でその変数のポインタ(オペランド/operand)が*でポインタがさすメモリへのアクセスができます。
なおC言語と違ってポインタ演算はないです。

sample.go
package main

import "fmt"

func main() {
    i, j := 42, 2701

    p := &i         // iのポインタを取得
    fmt.Println(*p) // 先ほどのiのポインタを使い読み込む
    *p = 21         // ポインタを利用してiを変更
    fmt.Println(i)  // 変更したものを見る

    p = &j         // jのポインタを取得
    *p = *p / 37   // divide j through the pointer
    fmt.Println(j) // see the new value of j
}

structs(構造体)

Structはフィールドで構成されています。
そしてstructを変数として代入することも可能です。その代入された変数へのアクセスには.を用いて扱えます。

これ以外にもアクセスにポインタを利用したアクセスやNAME:initDateを用いた初期値設定なども行えます。

structを用いてオブジェクト指向的な運用も可能です。

sample.go
package main

import "fmt"
//struct
type Vertex struct {
    //field
    X int
    Y int
}


func main() {
    //構造体内部の変更part1
    v1 := Vertex{}
    v1.X, v1.Y = 1,20
    fmt.Println(v.X, v.Y )
    //構造体内部の変更part2
    v2 := Vertex{1,20}
    fmt.Println(v2.X, v2.Y )
    //Pointerを利用したアクセス     
    v3 := Vertex{}
    p := &v3
    p.X = 1e3
    //初期値設定
    v4 := Vertex{X:1,Y:20}
}

Arrays (配列)

配列は[n] Typeで宣言できます。shortの宣言でも指定が可能です。
GoではArrayのサイズを変更することはできないですが他の機能で便利なものを提供しているのでカバーされるでしょう。

sample.go
package main

import "fmt"

func main() {
    var a [2] string
    a[0] = "Hello"
    a[1] = "World"
    fmt.Println(a[0], a[1])
    fmt.Println(a)

    primes := [6] int {2, 3, 5, 7, 11, 13}
    fmt.Println(primes[1])
}

Slices (スライス)

スライスは配列を参照するようなもので、スライスはどのデータも格納しておらず元の配列部分の列を指しています。このことからスライスを編集することで元の配列も変更されます。
スライスの構造として、[low:high]となっておりlow以上のhigh未満の配列番号となります。

primes := [6]int{2, 3, 5, 7, 11, 13}
var s []int = primes[0:4]

配列と同じようにstructなどの各種タイプを指定できます。

Slice literals(可変配列化)

配列には制限があったもののsliceを利用することによってリテラルの長さのない配列リテラルもどきを生成できるようになる。

//配列リテラル
[3] bool {true, false, false}

//スライスを利用した模擬配列リテラル
[] bool {true, false, false}

Slice length and capacity

Sliceを使う際に長さ(len)と容量(capactiy)の両方の情報を持っています。
sliceの長さはそれに含まれている要素数、容量は最初の要素から数えて、元となる配列の要素数。
その際に使われる文として

s := []int{2, 3, 5, 7, 11, 13}
s = s[:]
len(s) //6
cap(s) //6

Nil Slices(sliceの未入力値)

sliceのゼロ値はnilで、長さと容量ともに0値となっている状態です。

Creating a slice with make
(Makeを利用したスライスの生成方法)

makeを利用した生成も可能で

a := make ( []int, len, cap)
s := make ([]string, 7)

で指定できる。困ったときはここを見るといいかも。

Slices of slices (連想配列)

Goでの連想配列の設定の仕方として、このような指定の仕方がある。

board := [][]string{
    []string{"_", "_", "_"},
    []string{"_", "_", "_"},
    []string{"_", "_", "_"},
}

append to a slice (sliceに追加)

GoでのAppendはPHPのarray_pushのような形で追加できるが、追加先の変数を指定しなければいけない。

var s [] int
s = append(s, 0)
s = append(s, 9, 2,. 55, 1)

range (反復の際の取り出し)

PHPやJavaScriptなどの言語でいうforeachに近い動きです。

package main

import "fmt"

var pow = []int{1, 2, 4, 8, 16, 32, 64, 128}

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

さらにfor rangeのindex値は省略でき_,valで省略可能です。

ついで(sliceとrange)

package main

import "golang.org/x/tour/pic"

func Pic(dx, dy int) [][]uint8 {
    ret := make([][]uint8,dy)

    for i := range ret {
        ret[i] = make([]uint8, dx)
        for j := range ret [i] {
            ret[i][j] = uint8(i * j)
        }
    }

    return ret
}

func main() {
    pic.Show(Pic)
}

map(マップ)

mapはkeyの値が関連付いています。mapのゼロ値はnilでnilはkeyを持っていません

package main

import "fmt"

func main() {
    Map := make(map [string] int)
    Map["hoge"] = 1
    Map["huga"] = 12
    fmt.Println(Map["hoge"],Map["huga"])
}

他の方法での入力の仕方として、

package main

import "fmt"


var m = map[string]int{
    "hoge" : 12,
    "huga" : 24,
}

func main() {
    fmt.Println(m)
}

mapの操作

//更新
mapName[key] = element
//取得
element = m[key]
//削除
delete(m,key)
//要素確認
element, ok = m[key]

Function

Function values(関数は変数)

関数は変数他の変数のように関数をわたすことができます。

function := func (x string) bool {
    fmt.println(x)
    return true
}

Function closures (クロージャ)

Goの関数はクロージャです。これにより外部から変数を参照する関数値で、この変数は入っている関数を参照し変数へアクセスして変更できます。
その意味ではその関数は変数へのバインドされます。

test := func () {
    //code
}

fibonacci数列

package main

import "fmt"

func fibonacci() func(int) int {
    fib := 0
    return func (i int) int {
        ff := fibonacci()
        switch i {
            case 0 :
                fib = 0
            case 1 :
                fib = 1
            default:
                fib = ff(i-2) + ff(i-1)
        }
        return fib
    }
}

func main() {
    f := fibonacci()
    for i := 0; i < 12; i++ {
        fmt.Println(f(i))
    }
}
Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away