所有的参数传递都是值传递
- 其中引用类型变量存放的是内存地址值,传递的值自然也是内存地址值。
- 引用类型包括切片、映射、通道、接口、函数。
package demo
import (
"fmt"
"testing"
)
type Record struct {
Field string
}
func Call(record Record) {
record.Field = "recordValue"
fmt.Println("record.Field = ", record.Field)
}
func Test(t *testing.T) {
var record1 Record = Record{Field: "record1Value"}
var record2 Record = record1
record2.Field = "record2Value"
Call(record2)
fmt.Println("record1.Field = ", record1.Field)
fmt.Println("record2.Field = ", record2.Field)
}
输出结果:
record.Field = recordValue
record1.Field = record1Value
record2.Field = record2Value
切片类型作为参数传递的问题
调用 append 函数往切片追加元素时,可能会生成一个新的切片。
package demo
import (
"fmt"
"testing"
)
func Call(numbers []int) []int {
numbers = append(numbers, 1)
numbers = append(numbers, 2)
numbers = append(numbers, 3)
return numbers
}
func Test(t *testing.T) {
var numbers1 = []int{0}
numbers2 := Call(numbers1)
fmt.Println("numbers1 = ", numbers1)
fmt.Println("numbers2 = ", numbers2)
}
输出结果:
numbers1 = [0]
numbers2 = [0 1 2 3]
空接口 interface{} 并不像 C/C++ 中的 void*类型指针
空接口 interface{} 指向的结构体存放变量的类型和变量的内存地址值。
package demo
import (
"fmt"
"testing"
)
func Test(t *testing.T) {
var str *string = nil
var any1 interface{} = str
var any2 interface{} = nil
var any3 interface{} = any1
{
_, ok := any1.(*string)
fmt.Println("_, ok := any1.(*string); ok =", ok)
}
{
_, ok := any2.(*string)
fmt.Println("_, ok := any2.(*string); ok =", ok)
}
{
_, ok := any3.(*string)
fmt.Println("_, ok := any3.(*string); ok =", ok)
}
}
输出结果:
_, ok := any1.(*string); ok = true
_, ok := any2.(*string); ok = false
_, ok := any3.(*string); ok = true
值接收者的方法指向的是副本
package demo
import (
"fmt"
"testing"
)
type Record struct {
Field string
}
func (record Record) Call1(field string) {
record.Field = field
}
func (record *Record) Call2(field string) {
record.Field = field
}
func Test(t *testing.T) {
var record1 Record = Record{Field: "record1Value"}
record1.Call1("record1NewValue")
fmt.Println("record1.Field = ", record1.Field)
var record2 Record = Record{Field: "record2Value"}
(&record2).Call1("record2NewValue")
fmt.Println("record2.Field = ", record2.Field)
var record3 Record = Record{Field: "record3Value"}
record3.Call2("record3NewValue")
fmt.Println("record3.Field = ", record3.Field)
var record4 Record = Record{Field: "record4Value"}
(&record4).Call2("record4NewValue")
fmt.Println("record4.Field = ", record4.Field)
}
输出结果:
record1.Field = record1Value
record2.Field = record2Value
record3.Field = record3NewValue
record4.Field = record4NewValue
结构体方法重写不像 Java/C++ 那样支持父类调用子类方法
import (
"fmt"
"testing"
)
type BaseRecord interface {
Call() string
}
type RecordA struct {
}
func (record *RecordA) Call() string {
return record.DoCall()
}
func (record *RecordA) DoCall() string {
return "call RecordA.DoCall()"
}
type RecordB struct {
RecordA
}
func (record *RecordB) DoCall() string {
return "call RecordB.DoCall()"
}
func Test(t *testing.T) {
var record BaseRecord = &RecordB{}
fmt.Println(record.Call())
}
输出结果:
call RecordA.DoCall()