Go言語戦闘における配列の内部実装と基本機能

前に書く


  • さて、学習GOしているので、この記事で
  • ブログ投稿の内容は《GO语言实战》、読書ノートの1つです。
  • 主にアレイ関連の知識に関連

あなたの両親を除いて、世界中の誰もあなたをうまく扱うべきではありません。-風水オペラの王子様「ソードカムズ」


配列の内部実装と基本機能

配列はGO調和して切片おり、他の言語映射基础数据结构学んだ友人は配列に精通している必要があります。基本的に、すべての言語には配列の概念があります。

数组(Array)线性データ構造です连续のセットを使用して、のセット内存空间を格納し相同类型的数据ます。

内部実装

このGo言語では、配列は、同じタイプの要素の連続したブロックを格納するために使用される固定長のデータ型です。配列によって格納される型は、またはなどの組み込み型整型字符串または何かにすることができます结构类型

配列は、それらが占有するメモリのために連続して割り当てられます。CPUは、使用中のデータを長期間キャッシュできます。また、メモリは連続しており、インデックスの計算が簡単です。これにより、配列内のすべての要素をすばやく反復処理できます。配列の型情報は、要素にアクセスするたびにメモリ内で移動する必要のある距離を提供できます。

上記の文についての私の個人的な理解:

  • 配列構造な内存连续分配ので、簡単计算索引(要素の相対アドレス)等差数列であると同時に内存连续、非常によく使用できますCUP的缓存。にCPUアクセスする首地址と、自動的に从内存中加载当前数组其他元素到CUP Cache読み込まれ、読み込まれる量がCPU Cache Line決定されるためCPU、使用中のデータは次のようになります。長期間キャッシュされます。メモリが不連続である場合、それを読み取ることはできず、データ要素はメモリから繰り返し読み取ることしかできず、機能CPU Cacheを十分に活用することはできません。CPU Cache
  • 配列要素はインデックスによってすばやく繰り返すことができます。aが配列の最初のアドレスを表す場合、それa[0]はオフセットの位置、つまりオフセットの位置を表す0最初のアドレスであるため、計算されたメモリアドレスは次のことを行うだけで済みます。この式を使用すると、インデックスの確認を通じてメモリアドレスをすばやく繰り返すことができ、理論上の時間複製度は一定レベルになります。a[k]ktype_sizea[k]a[k]_address = base_address + k * type_size

宣言と初期化

声明数组内部类型に保存するデータと保存する必要のある要素を指定する必要がある場合数量

  • 配列を宣言し、ゼロ値に設定します
var arrays [5]int
  • 配列リテラルを使用して配列を宣言します
arrays := [5]int{
    
    10,12,13}
  • Go宣言された配列の長さを自動的に計算しましょう
array := [...]int{
    
    10, 20,30, 40, 50}
  • 配列を宣言して特定の要素の値を指定し、インデックス1と特定の値で2要素を初期化します
array := [5]int{
    
    1: 10, 2: 20}

配列を使用する

メモリレイアウトは連続しているため、配列は非常に効率的なデータ構造です。配列内の要素にアクセスするときは[]、演算子を使用してください。

  • 配列要素にアクセスする
//声明一个包含 5 个元素的整型数组
array := [5]int{
    
    10, 20, 30, 40, 50}
// 修改索引为 2 的元素的值
array[2] = 35

声明一个所有元素都是指针的数组を使用*运算符して、要素ポインタが指す値にアクセスできます。

  • ポインタの配列の要素にアクセスします
// 声明包含 5 个元素的指向整数的数组
// 用整型指针初始化索引为 0 和 1 的数组元素
array := [5]*int{
    
    0: new(int), 1: new(int)}
// 为索引为 0 和 1 的元素赋值
*array[0] = 10
*array[1] = 20

Go言語では、配列は値です。これは、配列を代入操作で使用できることを意味します。変数名は配列全体を表し、同じタイプの配列を別の配列に割り当てることができます

// 声明第一个包含 5 个元素的字符串数组
var array1 [5]string
// 声明第二个包含 5 个元素的字符串数组
// 用颜色初始化数组
array2 := [5]string{
    
    "Red", "Blue", "Green", "Yellow", "Pink"}
// 把 array2 的值复制到 array1
array1 = array2
  • コンパイラは、異なるタイプの配列が相互に割り当てられるのを防ぎます
package main

import "fmt"

func main() {
    
    
        fmt.Println("你好,世界")
        // 声明第一个包含 4 个元素的字符串数组
        var array1 [4]string

        // 声明第二个包含 5 个元素的字符串数组
        // 使用颜色初始化数组
        array2 := [5]string{
    
    "Red", "Blue", "Green", "Yellow", "Pink"}

        // 将 array2 复制给 array1
        array1 = array2
}

go vet試験

┌──[[email protected]]-[/usr/local/go/src/demo]
└─$go fmt array.go
array.go
┌──[[email protected]]-[/usr/local/go/src/demo]
└─$vim array.go
┌──[[email protected]]-[/usr/local/go/src/demo]
└─$go vet array.go
# command-line-arguments
vet: ./array.go:15:11: cannot use array2 (variable of type [5]string) as [4]string value in assignment
┌──[[email protected]]-[/usr/local/go/src/demo]
└─$

多次元配列

配列自体には1つの次元しかありませんが、複数の配列を組み合わせて多次元配列を作成できます。多次元配列を使用すると、親子関係のデータや座標系に関連付けられたデータを簡単に管理できます。

  • 2次元配列を宣言します
// 声明一个二维整型数组,两个维度分别存储 4 个元素和 2 个元素
var array [4][2]int
// 使用数组字面量来声明并初始化一个二维整型数组
array := [4][2]int{
    
    {
    
    10, 11}, {
    
    20, 21}, {
    
    30, 31}, {
    
    40, 41}}
// 声明并初始化外层数组中索引为 1 个和 3 的元素
array := [4][2]int{
    
    1: {
    
    20, 21}, 3: {
    
    40, 41}}
// 声明并初始化外层数组和内层数组的单个元素
array := [4][2]int{
    
    1: {
    
    0: 20}, 3: {
    
    1: 41}}
  • 2次元配列の要素にアクセスする
// 声明一个 2×2 的二维整型数组
var array [2][2]int
// 设置每个元素的整型值
array[0][0] = 10

タイプが同じである限り、多次元配列を相互に割り当てることができます

// 声明两个不同的二维整型数组
var array1 [2][2]int
var array2 [2][2]int
// 为每个元素赋值
array2[0][0] = 10
array2[0][1] = 20
array2[1][0] = 30
array2[1][1] = 40
  • 同じタイプの多次元配列割り当て
// 将 array2 的值复制给 array1
array1 = array2
  • インデックスを使用して多次元配列に値を割り当てます
// 将 array1 的索引为 1 的维度复制到一个同类型的新数组里
var array3 [2]int = array1[1]
// 将外层数组的索引为 1、内层数组的索引为 0 的整型值复制到新的整型变量里
var value int = array1[1][0]

関数間で配列を渡す

関数間で配列を渡すことは、メモリとパフォーマンスの点でコストのかかる操作です。在函数之间传递变量时,总是以值的方式传递的変数が配列の場合、それは、長さに関係なく、配列全体が全体としてコピーされ、関数に渡されることを意味します。

  • 関数間で大きな配列を渡すには、値渡しを使用します
// 声明一个需要 8 MB 的数组,创建一个包含 100 万个 int 类型元素的数组
var array [1e6]int
// 将数组传递给函数 foo
foo(array)
// 函数 foo 接受一个 100 万个整型值的数组
func foo(array [1e6]int) {
    
    
...
} 

foo関数が呼び出されるたびにスタックに割り当てる必要のある8 MBメモリ

この操作を処理するためのより良い、より効率的な方法があります。配列へのポインタを渡すだけなので、メモリデータでは8なくデータのバイトを8 MBスタックにコピーするだけで済みます。

  • 関数間で大きな配列を渡すためにポインタを使用する
// 分配一个需要 8 MB 的数组
var array [1e6]int
// 将数组的地址传递给函数 foo
foo(&array)
// 函数 foo 接受一个指向 100 万个整型值的数组的指针
func foo(array *[1e6]int) {
    
    
...
}

配列のアドレスを関数に渡すには、スタック上の8バイトのメモリをポインタに割り当てるだけです。

おすすめ

転載: blog.csdn.net/sanhewuyang/article/details/123244300