Golang配列とSlice,およびappend関数のトラップ

3195 ワード

Golangにおける配列の概念はCとほとんど変わらない.
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章でよく話しています.