Grammar
prototypes
In Go/src/builtin/builtin.go, the append is described as follows:
The Append built-in function appends elements to the end of a slice. If
//It has sufficient capacity, the destination are resliced to accommodate the
//new elements. If it does not, a new underlying array would be allocated.
Append returns the updated slice. It is therefore necessary
to store the//result of append, often in the variable holding the slice itself:
//
slice = Append (Slice, elem1, elem2)
// slice = append (slice, anotherslice ...)
As a special case, it was legal to append a string to a byte slice, like this:
// slice = append ([]byte ("Hello ")," World "...)
Func Append (Slice []type, Elems ... Type) []type
Key pointsAdd one or more elements behind a slice with append; the slice of append has a underlying array, which is the relationship between slice and array, and slice has a concept of length and capability; If Slice has the remaining space to add these new elements, then append will place the new element in the free space behind slice, and if slice's space is not enough to drop the new element, then you need to recreate an array, which may be alloc, It is also possible to assign this new array in a realloc way, which means that the new slice may be at the same starting address as the previous slice, or it may not be a new address. -In general, it's a new address. Once the new address has been assigned, the elements in the original slice are copied to the new slice one by one and returned.
analogy
This slice can be likened to C + + vectors. To this end, you can refer to the C + + source code anatomy 4.2.5 vector structure and memory management. Example Code
Package main
Import (
"FMT"
)
type Employee struct {
name string City
string
}
func (E *employee) string () string {
return FMT. Sprintf ("employee[address:%p, Name:%s, City:%s]", E, E.name, e.city)
}
var g_employees = []employee{}
// var g_employees = make ([]employee, 0, 4)
func Add (Employee *employee) {
g_employees = append (G_employees, *empl Oyee)
}
func debug () {
count: = Len (g_employees) for
I: = 0; i < count; i++ {
fmt. Printf ("%d:%s\n", I, & (G_employees[i]))
}
fmt. Println ()
}
func main () {one
: = employee{name: "Name1", City: "City1"}:
= employee{name: "name2 ", City:" City2 "}
Three: = employee{name: ' Name3 ', City: ' City3 '} four
: = employee{name: ' Name4 ', City: ' City4 '} Add (&one) debug () Add (&two) debug ()
Add (
&three)
debug ()
Add ( &four)
debug ()
}
Run Results
Case 1:var g_employees = []employee{} 0:employee[address:0xc42000e100, Name:name1, City:city1] 0:employee[address: 0XC4200101C0, Name:name1, City:city1] 1:employee[address:0xc4200101e0, name:name2, City:city2] 0:employee[address : 0xc420086000, Name:name1, City:city1] 1:employee[address:0xc420086020, name:name2, City:city2] 2:employee[address : 0xc420086040, Name:name3, City:city3] 0:employee[address:0xc420086000, name:name1, City:city1] 1:employee[addres s:0xc420086020, Name:name2, City:city2] 2:employee[address:0xc420086040, Name:name3, City:city3] 3:employee[addres s:0xc420086060, Name:name4, City:city4] case 2:var g_employees = make ([]employee, 0, 4) 0:employee[address:0xc4200 74000, Name:name1, City:city1] 0:employee[address:0xc420074000, name:name1, City:city1] 1:employee[address:0xc420 074020, Name:name2, City:city2] 0:employee[address:0xc420074000, name:name1, City:city1] 1:employee[address:0xc42 0074020, Name:name2, CITy:city2] 2:employee[address:0xc420074040, Name:name3, City:city3] 0:employee[address:0xc420074000, name:name1, C Ity:city1] 1:employee[address:0xc420074020, name:name2, City:city2] 2:employee[address:0xc420074040, Name:name3, C
Ity:city3] 3:employee[address:0xc420074060, Name:name4, City:city4]
Analysis
In debug printing, the address of the object is specially printed and processed. Through the output, you can have the following conclusion: When an capability is 0, add an element on the empty slice, add 1, 2, 3 will reallocate storage space, accompanied by the object copy. changing objects with constant pointers
If the object is stored in the slice, you should pay special attention when handling these objects with pointers. For example, now the global variable takes the first way:
var g_employees = []employee{}
The main () code should read:
Func Main () {one
: = employee{name: "Name1", City: "City1"}--:
= employee{name: "Name2", City: "City2"}
Three: = employee{name: ' Name3 ', City: ' City3 '} four
: = employee{name: ' Name4 ', City: ' City4 '}
Add (&one)
debug ()
var p *employee
p = & (G_employees[0])
FMT. Printf ("P:%s\n\n", p)
Add (&two)
debug ()
FMT. Printf ("P:%s\n\n", p)
Add (&three)
debug ()
FMT. Printf ("P:%s\n\n", p)
Add (&four)
debug ()
FMT. Printf ("P:%s\n\n", p)
}
Once an element has been added, a pointer is defined to point to the element. Operation Result:
0:employee[address:0xc420074000, Name:name1, City:city1]
p:employee[address:0xc420074000, name:name1, city:cit Y1]
0:employee[address:0xc420076140, name:name1, City:city1]
1:employee[address:0xc420076160, name:name2, City:city2]
p:employee[address:0xc420074000, name:name1, City:city1]
0:employee[address:0xc420082000, Name:name1, City:city1]
1:employee[address:0xc420082020, name:name2, City:city2]
2:employee[address:0xc42 0082040, Name:name3, City:city3]
p:employee[address:0xc420074000, name:name1, city:city1]
0:employee[addre ss:0xc420082000, Name:name1, City:city1]
1:employee[address:0xc420082020, name:name2, City:city2]
2:emplo yee[address:0xc420082040, Name:name3, City:city3]
3:employee[address:0xc420082060, Name:name4, City:city4]
p:employee[address:0xc420074000, Name:name1, City:city1]
You can see that the address pointed to by the pointer remains the same, but it is not the object we expected. work
The
Now stores the object address in slice, not the object. Example One
Package main import ("FMT") type Employee struct {name string City string} func (e *employee) string () s Tring {return FMT. Sprintf ("employee[address:%p, Name:%s, City:%s]", E, E.name, e.city)} var g_employees = []*employee{} func Add (Emplo Yee *employee) {g_employees = append (G_employees, Employee)} func debug () {count: = Len (g_employees) for I : = 0; I < count; i++ {fmt. Printf ("%d:%s\n", I, G_employees[i])} FMT. Println ()} func main () {one: = Employee{name: "Name1", City: "City1"}, and "Employee{name": "Name2", City: "City2
'} Three: = Employee{name: ' Name3 ', City: ' City3 '} Four: = Employee{name: ' Name4 ', City: ' City4 '} Add (&one) Debug () var p *employee p = g_employees[0] FMT. Printf ("P:%s\n\n", p) Add (&two) debug () Fmt. Printf ("P:%s\n\n", p) Add (&three) debug () Fmt. Printf ("P:%s\n\n", p) Add (&four) debug () Fmt. Printf ("P:%s\n\n", p)
}
Operation Result:
0:EMPLOYEE[ADDRESS:0XC42000E1A0, Name:name1, City:city1]
p:employee[address:0xc42000e1a0, name:name1, city:cit Y1]
0:employee[address:0xc42000e1a0, name:name1, City:city1]
1:employee[address:0xc42000e1c0, name:name2, City:city2]
p:employee[address:0xc42000e1a0, name:name1, City:city1]
0:employee[address:0xc42000e1a0, Name:name1, City:city1]
1:employee[address:0xc42000e1c0, name:name2, City:city2]
2:employee[address:0xc42 000E1E0, Name:name3, City:city3]
p:employee[address:0xc42000e1a0, name:name1, city:city1]
0:employee[addre SS:0XC42000E1A0, Name:name1, City:city1]
1:employee[address:0xc42000e1c0, name:name2, City:city2]
2:emplo YEE[ADDRESS:0XC42000E1E0, Name:name3, City:city3]
3:employee[address:0xc42000e200, Name:name4, City:city4]
P:EMPLOYEE[ADDRESS:0XC42000E1A0, Name:name1, City:city1]
Example Two
Package main
Import (
"FMT"
)
type Employee struct {
name string City
string
}
func (E *employee) string () string {
return FMT. Sprintf ("employee[address:%p, Name:%s, City:%s]", E, E.name, e.city)
}
var g_employees = []*employee{}
F UNC Add (index int) {
g_employees = append (g_employees,
&employee{
fmt. Sprintf ("name%d", index),
FMT. Sprintf ("city%d", Index)})
}
func debug () {
count: = Len (g_employees) for
I: = 0; i < count; i++ { C20/>fmt. Printf ("%d:%s\n", I, G_employees[i])
}
fmt. Println ()
}
func main () {
Add (1)
debug ()
var p *employee
p = g_employees[0]
fmt. Printf ("P:%s\n\n", p)
Add (2)
debug ()
FMT. Printf ("P:%s\n\n", p)
Add (3)
debug ()
FMT. Printf ("P:%s\n\n", p)
Add (4)
debug ()
FMT. Printf ("P:%s\n\n", p)
}
The result of the operation is unchanged.