方法
方法是什么?
在Go语言中,方法是在包代码级别定义的,多了一个接收者,方法就是与类型相关联的函数,可以在类型的实例上调用这些函数,从而实现对类型的操作。
类型
类型可以由什么组成?
在Go语言中,类型可以使用结构体字面量、任何基本类型或者复合类型字面量定义具体类型。
类型声明
type Student struct {
Name string
Age int
}
type S string
type m map[string]int
type f func(string)
方法-声明调用
如何声明调用方法?
声明函数中添加接收值,调用方法可以通过类型的实例化点出来。
type Student struct {
Name string
Age int
}
func (s *Student) f() string {
return "Name:" + s.Name
}
func main() {
student := Student{
Name: "张三",
Age: 16,
}
result := student.f()
fmt.Println(result)
}
方法-指针接收者与值接收者
指针接受者和值接收值的区别?
在Go语言中,值接收者方法的接收者是该类型的副本,所以修改接收者是不影响原始值。指针方法方法的接收者是该类型的指针。
type Student struct {
Age int
LastUpdated time.Time
}
func (s *Student) Increment() {
s.Age++
s.LastUpdated = time.Now()
}
func (s Student) String() string {
return s.LastUpdated.String()
}
func main() {
var s Student
fmt.Println(s.String())
s.Increment()
fmt.Println(s.String())
}
type Student struct {
Age int
LastUpdated time.Time
}
func (s *Student) Increment() {
s.Age++
s.LastUpdated = time.Now()
}
func (s Student) String() string {
return s.LastUpdated.String()
}
func 参数是值(s Student) {
s.Increment()
fmt.Println(s.String())
}
func 参数是指针(s *Student) {
s.Increment()
// (*s).Increment()
fmt.Println(s.String())
}
func main() {
s := Student{}
参数是值(s)
fmt.Println(s.String())
参数是指针(&s)
fmt.Println(s.String())
}
方法-内嵌字段的方法
在Go语言中,内嵌字段声明的任何字段和方法都会被提升到所包含的结构体。
如果结构体的字段或者方法与内嵌的字段或者方法同名,会被覆盖,则需要使用内嵌的字段的类型引用被覆盖的的字段或者方法。
type Address struct {
Name string
}
type Person struct {
Name string
Address // 匿名成员
}
func (e Address) Description() string {
fmt.Println(e.Name)
return e.Name
}
func (e Person) Description() string {
fmt.Println(e.Name)
return e.Name
}
func main() {
// 创建 Person 实例并初始化匿名成员字段
person := Person{
Name: "张三",
Address: Address{
Name: "西安",
},
}
person.Description()
person.Address.Description()
}
type Inner struct {
x int
}
type Outer struct {
x int
Inner
}
func main() {
o := Outer{
x: 1,
Inner: Inner{1},
}
fmt.Println(o.Inner.x)
fmt.Println(o.x)
}
type Inner struct {
}
func (c Inner) P() string {
return "张三"
}
func (c Inner) P1() string {
return c.P()
}
type Outer struct {
Inner
}
func (c Outer) P() string {
return "李四"
}
func main() {
o := Outer{
Inner: Inner{},
}
fmt.Println(o.P1())
fmt.Println(o.P())
fmt.Println(o.Inner.P())
}
方法-特性在方法中处理nil实例
在 Go 语言中,当你尝试在一个 nil 接口值上调用方法时,会引发运行时错误(panic)。这种情况通常会发生在接口的底层值为
nil
的情况下。在 Go 中,对于接收者是指针类型的方法,可以在 nil 指针上调用这些方法。这种行为在某些情况下是很有用的,并且是 Go 语言设计的一个特性。如果是值类型 就会panic
/*
在 Go 中,对于接收者是指针类型的方法,可以在 nil 指针上调用这些方法。这种行为在某些情况下是很有用的,并且是 Go 语言设计的一个特性。
如果时值类型 就会pannic
*/
type Circle struct {
Radius float64
}
func (c *Circle) Area() float64 {
if c == nil {
return 0
}
return 3.14 * c.Radius * c.Radius
}
func main() {
var c *Circle // c 是一个指向 Circle 类型的指针变量,但尚未初始化
fmt.Println(c.Area())
}
type Circle struct {
Radius float64
}
func (c Circle) Area() float64 {
return 3.14 * c.Radius * c.Radius
}
func main() {
var c *Circle // c 是一个指向 Circle 类型的指针变量,但尚未初始化
fmt.Println(c.Area()) // 这里会引发 panic,因为 c 是一个 nil
}
方法-实例化类型的方法赋给变量
在Go语言中,可以把类型的方法、实例化类型的方法赋给变量。
/*
实例化类型的方法赋给变量
*/
type Adder struct {
start int
}
func (a *Adder) AddTo(val int) int {
return a.start + val
}
func main() {
a := Adder{start: 10}
f := a.AddTo
fmt.Printf("类型是%T", f)
fmt.Println(a.AddTo(1))
}
方法-类型本身的方法赋给变量
/*
类型本身的方法赋给变量
*/
type Adder struct {
start int
}
func (a Adder) AddTo(val int) int {
return a.start + val
}
func main() {
//类型本身的方法赋给变量
f := Adder.AddTo
fmt.Println(f(Adder{start: 10}, 1))
}