_言語を行くより多くの種類:構造体、スライスとマッピング

その他のタイプ:構造体、スライスおよびマッピングは
、既存のタイプに基づいて新しい型を定義する方法を学ぶ:このレッスンでは、構造体、配列、スライス、およびマップをカバーしています。

行く-ZHグループ翻訳、執筆者のグループを作成します。
https://tour.go-zh.org/moretypes/1

  • ポインタ

Goがポインタを持っています。メモリ・アドレス・ポインタの値を保存します。

型が*TポインタであるTポインタのタイプ値。その値はゼロですnil

var p *int

& 演算子は、そのオペランドへのポインタを生成します。

i := 42
p = &i

* オペレータは、下のポインタ値を示します。

fmt.Println(*p) // 通过指针 p 读取 i
*p = 21         // 通过指针 p 设置 i

これは一般に「間接参照」またはと呼ばれる「リダイレクト」。

そして、異なるCは、何のポインタ演算を行きます。

// +build OMIT

package main

import "fmt"

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

    p := &i         // 指向 i
    fmt.Println(*p) // 通过指针读取 i 的值
    *p = 21         // 通过指针设置 i 的值
    fmt.Println(i)  // 查看 i 的值

    p = &j         // 指向 j
    *p = *p / 37   // 通过指针对 j 进行除法运算
    fmt.Println(j) // 查看 j 的值
}
  • 構造

構造(struct)フィールド(フィールド)の集合です。

// +build OMIT

package main

import "fmt"

type Vertex struct {
    X int
    Y int
}

func main() {
    fmt.Println(Vertex{1, 2})
}
  • 構造体のフィールド

フィールドは、アクセスにドット構造を使用しています。

// +build OMIT

package main

import "fmt"

type Vertex struct {
    X int
    Y int
}

func main() {
    v := Vertex{1, 2}
    v.X = 4
    fmt.Println(v.X)
}
  • 構造体ポインタ

構造体のフィールドは、構造体へのポインタによってアクセスすることができます。

我々は構造体へのポインタを持っている場合はp、次のことができ(*p).X、そのフィールドにアクセスしますX言語はまた、私たちは、暗黙の間接参照を使用して直接書き込むことができますので、しかし、これは、あまりにも長い間ったらしい書くp.Xことに。

// +build OMIT

package main

import "fmt"

type Vertex struct {
    X int
    Y int
}

func main() {
    v := Vertex{1, 2}
    p := &v
    p.X = 1e9
    fmt.Println(v)
}
  • 構造文法

構造文法が記載されている直接して、新しい値のフィールド構造を割り当てることができます。

使用するName:フィールドの一部のみを一覧表示する構文を。(フィールド名の順序とは無関係に。)

特別な接頭辞は&構造体へのポインタを返します。

// +build OMIT

package main

import "fmt"

type Vertex struct {
    X, Y int
}

var (
    v1 = Vertex{1, 2}  // 创建一个 Vertex 类型的结构体
    v2 = Vertex{X: 1}  // Y:0 被隐式地赋予
    v3 = Vertex{}      // X:0 Y:0
    p  = &Vertex{1, 2} // 创建一个 *Vertex 类型的结构体(指针)
)

func main() {
    fmt.Println(v1, p, v2, v3)
}
  • 配列

タイプの[n]T表現が有するタイプの値の配列を。nT

表現

var a [10]int

これは、変数になりますa10個の整数の配列として宣言します。

配列タイプ、したがってアレイのサイズのその長さの一部を変更することはできません。これが限界であるように見えますが、それは、OKですGoは、配列を使用するためのより便利な方法を提供します。

// +build OMIT

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)
}
  • 薄切

各配列のサイズは固定されています。スライスは、動的で柔軟な視野角を提供するために、アレイ素子のサイズでした。実際には、スライスは、より一般的にアレイより使用されています。

タイプは、[]T要素タイプ表すTスライスのを。

2つの添字、すなわち、下限と上限、コロンで区切られた両方によって定義されるスライス。

a[low : high]

これは、最初の要素を含むが、最後の要素を除いて、ハーフオープン範囲を選択します。

次の式は含まれていたスライス作成a1-3からの要素のインデックスを:

a[1:4]
// +build OMIT

package main

import "fmt"

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

    var s []int = primes[1:4]
    fmt.Println(s)
}
  • 配列への参照のようにスライス

スライスは、それは単に基本的な配列のいくつかを説明し、任意のデータを格納しません。

変更のスライスは、対応する要素を基本となる配列要素を変更します。

元の配列部分と共有は、このような修飾が観察されます。

// +build OMIT

package main

import "fmt"

func main() {
    names := [4]string{
        "John",
        "Paul",
        "George",
        "Ringo",
    }
    fmt.Println(names)

    a := names[0:2]
    b := names[1:3]
    fmt.Println(a, b)

    b[0] = "XXX"
    fmt.Println(a, b)
    fmt.Println(names)
}
  • スライス文法

文法文法ない配列セクション同様の長さ。

これは、文法の配列です。

[3]bool{true, true, false}

この下に一方と上記と同じ配列を作成し、そのスライスへの参照を構築します。

[]bool{true, true, false}
// +build OMIT

package main

import "fmt"

func main() {
    q := []int{2, 3, 5, 7, 11, 13}
    fmt.Println(q)

    r := []bool{true, false, true, true, false, true}
    fmt.Println(r)

    s := []struct {
        i int
        b bool
    }{
        {2, true},
        {3, false},
        {5, true},
        {7, true},
        {11, false},
        {13, true},
    }
    fmt.Println(s)
}
  • デフォルトの動作スライス

スライス中は、境界のデフォルトの動作をオーバーライドするためにそれを使用することができます。

結合された下部スライスのデフォルト値は0、上限は、スライスの長さです。

アレイの場合

var a [10]int

、次のセクションでは、等価です。

a[0:10]
a[:10]
a[0:]
a[:]
// +build OMIT

package main

import "fmt"

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

    s = s[1:4]
    fmt.Println(s)

    s = s[:2]
    fmt.Println(s)

    s = s[1:]
    fmt.Println(s)
}
  • スライスの長さと容量

スライスはあり長さ容量を

スライスの長さは、それが含まれている要素の数です。

容量は、下にあるアレイ素子の数の最後までその開始から最初の要素内のスライスの数です。

スライスのs長さと容量の表現によるlen(s)と、cap(s)買収しました。

限り十分な容量として、あなたは再びスライスでスライスを拡張することができます。長い(その容量の範囲を超えて拡大しようとしている)の容量よりもそれを作る、サンプルプログラムをスライス変更し、何が起こるか見てみてください。

// +build OMIT

package main

import "fmt"

func main() {
    s := []int{2, 3, 5, 7, 11, 13}
    printSlice(s)

    // 截取切片使其长度为 0
    s = s[:0]
    printSlice(s)

    // 拓展其长度
    s = s[:4]
    printSlice(s)

    // 舍弃前两个值
    s = s[2:]
    printSlice(s)
}

func printSlice(s []int) {
    fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s)
}
  • nilのスライス

ゼロ値スライスですnil

ゼロスライスの長さと0の容量となし下地アレイ。

// +build OMIT

package main

import "fmt"

func main() {
    var s []int
    fmt.Println(s, len(s), cap(s))
    if s == nil {
        fmt.Println("nil!")
    }
}
  • メイクでスライスを作成します。

組み込み関数とのスライスが可能makeに作成され、これはあなたが動的配列を作成する方法です。

make 関数はゼロの配列要素の値を割り当て、そのスライスの参照を返します。

a := make([]int, 5)  // len(a)=5

その容量を指定するには、する必要がmake三番目のパラメータを渡します。

b := make([]int, 0, 5) // len(b)=0, cap(b)=5

b = b[:cap(b)] // len(b)=5, cap(b)=5
b = b[1:]      // len(b)=4, cap(b)=4
// +build OMIT

package main

import "fmt"

func main() {
    a := make([]int, 5)
    printSlice("a", a)

    b := make([]int, 0, 5)
    printSlice("b", b)

    c := b[:2]
    printSlice("c", c)

    d := c[2:5]
    printSlice("d", d)
}

func printSlice(s string, x []int) {
    fmt.Printf("%s len=%d cap=%d %v\n",
        s, len(x), cap(x), x)
}
  • スライススライス

スライスは、任意のタイプ、さらには他のスライスを含むことができます。

// +build OMIT

package main

import (
    "fmt"
    "strings"
)

func main() {
    // 创建一个井字板(经典游戏)
    board := [][]string{
        []string{"_", "_", "_"},
        []string{"_", "_", "_"},
        []string{"_", "_", "_"},
    }

    // 两个玩家轮流打上 X 和 O
    board[0][0] = "X"
    board[2][2] = "O"
    board[1][2] = "X"
    board[1][0] = "O"
    board[0][2] = "X"

    for i := 0; i < len(board); i++ {
        fmt.Printf("%s\n", strings.Join(board[i], " "))
    }
}
  • 追加の要素をスライスします

スライスは一般的操作で使用される新しい要素を追加し、ビルトイン行く提供することを目的としてappend機能します。組み込み関数は、[ https://go-zh.org/pkg/builtin/#append ] [ドキュメント]に詳細にこの機能を有しています。

func append(s []T, vs ...T) []T

append最初のパラメータは、s要素のタイプであるTセクションは、他のタイプのT値がスライスの最後に追加されるであろう。

append 結果は、すべての元の要素に加えて新たに追加されたセクションの元素を含むスライスです。

ときにs元の配列の時間が与えられたすべての値を収容するには小さすぎる、それはより大きな配列が割り当てられます。返されたスライスは、この新しく割り当てられた配列を指します。

(スライスの詳細については、記事を読んでください[[ https://blog.go-zh.org/go-slices-usage-and-internals ] [セクションを行く:使用と自然が]]。)

// +build OMIT

package main

import "fmt"

func main() {
    var s []int
    printSlice(s)

    // 添加一个空切片
    s = append(s, 0)
    printSlice(s)

    // 这个切片会按需增长
    s = append(s, 1)
    printSlice(s)

    // 可以一次性添加多个元素
    s = append(s, 2, 3, 4)
    printSlice(s)
}

func printSlice(s []int) {
    fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s)
}
  • 範囲

forループrange形又はマップセクションを横断することができます。

使用する場合for、各反復を介してタイムスライシングサイクルを2つの値を返します。最初の要素のコピーが現在の要素のインデックス値に対応する第2のインデックスです。

// +build OMIT

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 i, _ := range pow
for _, value := range pow

あなただけのインデックスが必要な場合は、2番目の変数を無視します。

for i := range pow
// +build OMIT

package main

import "fmt"

func main() {
    pow := make([]int, 10)
    for i := range pow {
        pow[i] = 1 << uint(i) // == 2**i
    }
    for _, value := range pow {
        fmt.Printf("%d\n", value)
    }
}
  • 演習:スライス

達成Picこれは、の長さを返す必要がありdy、スライスを前記各要素の長さdx、要素型uint8スライスの。このプログラムを実行する場合は、階調各整数値(よく、実際には、青の値である)として解釈し、それが対応する画像を表示します。

あなたが決定する画像を選択します。いくつかの興味深い機能には(x+y)/2x*yx^yx*log(y)x%(y+1)

(ヒント:割り当てるためにループを使用し[][]uint8、それぞれを[]uint8、使用してくださいuint8(intValue)型変換の間、あなたが使用する可能性があるmath機能パッケージを。)

// +build no-build OMIT

package main

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

func Pic(dx, dy int) [][]uint8 {
}

func main() {
    pic.Show(Pic)
}
  • マッピング(map

マッピングは、キーを値にマップします。

ゼロ値のマッピングnilnilどちらの結合をマッピングやキーを追加します。

make 関数マッピングの指定された型を返し、そのスタンバイを初期化します。

// +build OMIT

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"])
}
  • 文法のマッピング

マッピング文法と構造似ていますが、キーの名前を指定する必要があります。

// +build OMIT

package main

import "fmt"

type Vertex struct {
    Lat, Long float64
}

var m = map[string]Vertex{
    "Bell Labs": Vertex{
        40.68433, -74.39967,
    },
    "Google": Vertex{
        37.42202, -122.08408,
    },
}

func main() {
    fmt.Println(m)
}
  • 文法のマッピング(続き)

トップレベルのタイプがちょうどタイプの名前である場合は、文法の要素からそれを省略することができます。

// +build OMIT

package main

import "fmt"

type Vertex struct {
    Lat, Long float64
}

var m = map[string]Vertex{
    "Bell Labs": {40.68433, -74.39967},
    "Google":    {37.42202, -122.08408},
}

func main() {
    fmt.Println(m)
}
  • マッピングの変更

マッピングm挿入または変更された要素:

m[key] = elem

要素を取得します:

elem = m[key]

要素を削除します:

delete(m, key)

二重検出によるキーの割り当てがあるかどうか:

elem, ok = m[key]

場合keyにはm中央の、okそれはtrue、そうでない場合、okですfalse

場合keyマップでない場合、elemゼロ値要素には、マッピング・タイプです。

キーマッピングからの読み出しが存在しない場合同様に、結果はゼロ値の要素型マッピングです。

注意:あなたの場合elemまたはok宣言されていないが、あなたは短い変数宣言を使用することができます。

elem, ok := m[key]
// +build OMIT

package main

import "fmt"

func main() {
    m := make(map[string]int)

    m["Answer"] = 42
    fmt.Println("The value:", m["Answer"])

    m["Answer"] = 48
    fmt.Println("The value:", m["Answer"])

    delete(m, "Answer")
    fmt.Println("The value:", m["Answer"])

    v, ok := m["Answer"]
    fmt.Println("The value:", v, "Present?", ok)
}
  • 演習:マッピング

達成WordCountこれは、文字列含むマップを返す必要がありs、それぞれ「単語」の数を。この関数はwc.Test、この機能のための一連のテストケースを実行し、成功か失敗かを出力します。

あなたは[見つかりますhttps://go-zh.org/pkg/strings/#Fields ] [strings.Fields]]便利。

// +build OMIT

package main

import (
    "golang.org/x/tour/wc"
)

func WordCount(s string) map[string]int {
    return map[string]int{"x": 1}
}

func main() {
    wc.Test(WordCount)
}
  • 関数の値

関数も値です。それらが同じであるように、他の値を渡すことができます。

関数の値は、パラメータまたは関数の戻り値として使用することができます。

// +build OMIT

package main

import (
    "fmt"
    "math"
)

func compute(fn func(float64, float64) float64) float64 {
    return fn(3, 4)
}

func main() {
    hypot := func(x, y float64) float64 {
        return math.Sqrt(x*x + y*y)
    }
    fmt.Println(hypot(5, 12))

    fmt.Println(compute(hypot))
    fmt.Println(compute(math.Pow))
}
  • 閉鎖機能

閉鎖かもしれ機能を移動します。クロージャは、体外の変数の関数を指し、関数値です。この機能は、他の言葉で、これらの変数の機能が一緒に「結合」され、その基準値の変数にアクセスして付与することができます。

例えば、関数はadderクロージャを返します。それぞれの閉鎖は、それぞれにバインドされているsum上部の変数。

// +build OMIT

package main

import "fmt"

func adder() func(int) int {
    sum := 0
    return func(x int) int {
        sum += x
        return sum
    }
}

func main() {
    pos, neg := adder(), adder()
    for i := 0; i < 10; i++ {
        fmt.Println(
            pos(i),
            neg(-2*i),
        )
    }
}
  • 演習:フィボナッチ閉鎖

のは楽しい事をする機能を使用してみましょう。

実施fibonacci閉鎖[を返す関数(クロージャ)を返す関数を、[ https://zh.wikipedia.org/wiki/%E6%96%90%E6%B3%A2%E9%82%A3 91はE5の%A5 %%%% 95%B0 E6 E5%88%97%である ] (0, 1, 1, 2, 3, 5, ...)[フィボナッチ]

// +build no-build OMIT

package main

import "fmt"

// 返回一个“返回int的函数”
func fibonacci() func() int {
}

func main() {
    f := fibonacci()
    for i := 0; i < 10; i++ {
        fmt.Println(f())
    }
}
  • おめでとうございます!

あなたはこのコースを完了しました!

あなたはどのような次の学習を見て、[モジュール]の[/リスト] [リスト]に戻るか、継続することができ、[[ JavaScriptを:クリックしてコース]の後ろに(「.next-ページ」)]、[]を。

おすすめ

転載: www.cnblogs.com/pdev/p/10928735.html