Golang配列とSlice,およびappend関数のトラップ
3195 ワード
Golangにおける配列の概念はCとほとんど変わらない.
1.配列を宣言
2.配列ポインタを宣言する
3.Slice
sliceは単純に配列を指すポインタではなく、構造体(ポインタ、長さ、容量を含む)です.
上には「nilスライス」が作られていますが、golangのnilも単純な空のポインタではなく、Javaのnullとは異なる意味を持っていることに気づきます.
Javaに次のコードがある場合:
これはobjectという変数がメモリの参照ではないことを示します.
Golangに次のコードがある場合:
sliceがnilスライスによって付与されることを示し、nilスライスは構造体の変数が「0値」である.すなわち、nilスライス{ポインタ(NULL)、長さ(0)、容量(0)}
4.Sliceの付与
一方のSliceが他方のSliceに割り当てられている場合、slice 2=sliceのような下位配列を共有している場合、slice 2のポインタはsliceのポインタと下位層の同じ配列を指します.
インデックスを使用してスライスを作成することもできます.
Sliceの長さは彼がアクセスできる区間を表し,容量はappend操作の区間を表す.appendが設定された区間を超えると、Sliceの下部が拡張されます
5.トラップのあるappend操作
この部分は、appendが設定区間を超えると、Sliceの下地が拡張する.この言葉は詳しく説明しますね.
具体的に言いたいのは以下の例です.
だから私がなぜappendに罠があると言ったのか知っていますか?append操作により、同じ下位配列を使用していた2つのSlice変数が、異なる下位配列を使用するようになる可能性があります.
この部分については「go言語実戦」の第4章でよく話しています.
1.配列を宣言
var array [5]int // 。
var array2 [5]int
array2=array // , 。
//
func test(){
var array =[5]int{2,3,4,5,6}
var array2 [5]int
array2=array
array[1]=9
fmt.Printf("array:%v
",array) // :array:[2 9 4 5 6]
fmt.Printf("array2:%v
",array2) // :array2:[2 3 4 5 6]
}
2.配列ポインタを宣言する
var array *[5]int // 。
var array2 *[5]int
array2=array // , , 。
//
func test(){
var array =&[5]int{2,3,4,5,6}
var array2 *[5]int
array2=array
array[1]=9
fmt.Printf("array:%v
",array) // array:&[2 9 4 5 6]
fmt.Printf("array2:%v
",array2) //array2:&[2 9 4 5 6]
}
3.Slice
sliceは単純に配列を指すポインタではなく、構造体(ポインタ、長さ、容量を含む)です.
// nil
var slice []int
上には「nilスライス」が作られていますが、golangのnilも単純な空のポインタではなく、Javaのnullとは異なる意味を持っていることに気づきます.
Javaに次のコードがある場合:
Object object=null;
これはobjectという変数がメモリの参照ではないことを示します.
Golangに次のコードがある場合:
var slice []int=nil
sliceがnilスライスによって付与されることを示し、nilスライスは構造体の変数が「0値」である.すなわち、nilスライス{ポインタ(NULL)、長さ(0)、容量(0)}
4.Sliceの付与
一方のSliceが他方のSliceに割り当てられている場合、slice 2=sliceのような下位配列を共有している場合、slice 2のポインタはsliceのポインタと下位層の同じ配列を指します.
インデックスを使用してスライスを作成することもできます.
//
// 5
slice := []int{10, 20, 30, 40, 50}
//
// 2 , 4
newSlice := slice[1:3]
/ ,
// 1 , 2
newSlice2 := slice[2:3:4]
Sliceの長さは彼がアクセスできる区間を表し,容量はappend操作の区間を表す.appendが設定された区間を超えると、Sliceの下部が拡張されます
5.トラップのあるappend操作
この部分は、appendが設定区間を超えると、Sliceの下地が拡張する.この言葉は詳しく説明しますね.
具体的に言いたいのは以下の例です.
func test(){
var array =[]int{1,2,3,4,5}// len:5,capacity:5
var newArray=array[1:3]// len:2,capacity:4 ( , append)
fmt.Printf("%p
",array) //0xc420098000
fmt.Printf("%p
",newArray) //0xc420098008 newArray array[1] ,
fmt.Printf("%v
",array) //[1 2 3 4 5]
fmt.Printf("%v
",newArray) //[2 3]
newArray[1]=9 // array、newArray
fmt.Printf("%v
",array) // [1 2 9 4 5]
fmt.Printf("%v
",newArray) // [2 9]
newArray=append(newArray,11,12)//append ,array len capacity ,newArray len 4,capacity:4。 newArray
fmt.Printf("%v
",array) //[1 2 9 11 12] // newArray append ,array[3],array[4]
fmt.Printf("%v
",newArray) //[2 9 11 12]
newArray=append(newArray,13,14) // newArray len capacity, append capacity ,
// ,append ( ), array , 。
fmt.Printf("%p
",array) //0xc420098000
fmt.Printf("%p
",newArray) //0xc4200a0000
fmt.Printf("%v
",array) //[1 2 9 11 12]
fmt.Printf("%v
",newArray) //[2 9 11 12 13 14] y
}
だから私がなぜappendに罠があると言ったのか知っていますか?append操作により、同じ下位配列を使用していた2つのSlice変数が、異なる下位配列を使用するようになる可能性があります.
この部分については「go言語実戦」の第4章でよく話しています.