企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
## 方法和接收者 Go语言中的方法(Method)是一种作用于特定类型变量的函数。这种特定类型变量叫做接收者(Receiver)。接收者的概念就类似于其他语言中的this或者 self。 方法的定义格式如下: ~~~ func (接收者变量 接收者类型) 方法名(参数列表) (返回参数) { 函数体 } ~~~ 特性: • 只能为当前包内命名类型定义方法; • 参数 receiver 可任意命名,如方法中未曾使用 ,可省略参数名; • 参数 receiver 类型可以是 T 或 *T。基类型 T 不能是接口或指针; • 不支持方法重载,receiver 只是参数签名的组成部分; • 接收者变量:接收者中的参数变量名在命名时,官方建议使用接收者类型名的第一个小写字母,而不是self、this之类的命名。例如,Person类型的接收者变量应该命名为 p,Connector类型的接收者变量应该命名为c等; • 接收者类型:接收者类型和参数类似,可以是指针类型和非指针类型(编译器自动转换); ~~~ //Person 结构体 type Person struct { name string age int8 } //NewPerson 构造函数 func NewPerson(name string, age int8) *Person { return &Person{ name: name, age: age, } } func (p Person) Dream() { fmt.Printf("%s的梦想是学好Go语言!\n", p.name) } // 指针调用,为避免内存拷贝,通常使用该方式 func (p *Person) Running() { fmt.Printf("%s在跑步!", p.name) } func main() { p1 := NewPerson("测试", 25) p1.Dream() } ~~~ ### 指针类型接收者适用场景 ~~~ 1. 适用于对方法内部的接收器所做的改变应该对调用者可见时 2. 接收者是拷贝代价比较大的大对象 3. 保证一致性,如果有某个方法使用了指针接收者,那么其他的方法也应该使用指针接收者 ~~~ ### 匿名字段的方法 属于结构体的匿名字段的方法可以被直接调用,就好像这些方法是属于定义了匿名字段的结构体一样 ~~~go type address struct { city string state string } func (a address) fullAddress() { fmt.Printf("Full address: %s, %s", a.city, a.state) } type person struct { firstName string lastName string address } func main() { p := person{ firstName: "Elon", lastName: "Musk", address: address { city: "Los Angeles", state: "California", }, } p.fullAddress() //访问 address 结构体的 fullAddress 方法 } ~~~ ### 在非结构体上的方法 到目前为止,我们只在结构体类型上定义方法。也可以在非结构体类型上定义方法,但是有一个问题。为了在一个类型上定义一个方法,方法的接收器类型定义和方法的定义应该在同一个包中。到目前为止,我们定义的所有结构体和结构体上的方法都是在同一个`main`包中,因此它们是可以运行的 ~~~go package main func (a int) add(b int) { } func main() { } // 在上面程序中,我们尝试把一个`add`方法添加到内置的类型`int`。这是不允许的,因为`add`方法的定义和`int`类型的定义不在同一个包中。该程序会抛出编译错误`cannot define new methods on non-local type int` ~~~ 让该程序工作的方法是为内置类型 int 创建一个类型别名,然后创建一个以该类型别名为接收器的方法。 ~~~go package main import "fmt" type myInt int func (a myInt) add(b myInt) myInt { return a + b } func main() { num1 := myInt(5) num2 := myInt(10) sum := num1.add(num2) fmt.Println("Sum is", sum) } ~~~