一、方法定义
-
什么是方法?
方法是作用于自定义数据类型上的,只可以由该数据类型声明的变量调用!
定义:func (type type) funcName(行参列表) (返回列表) { }
调用:变量.函数名(实参列表)
-
案例1:自定义结构体绑定的方法
type Utils struct { M int N int } func (util Utils) PrintJX() (area int) { for i := 0; i < util.M; i++ { for i := 0; i < util.N; i++ { fmt.Print("*") } fmt.Println() } area = util.M * util.N return } func main() { // 调用 util := Utils{1,2} util.PrintJX() }
-
案例2:自定义数据类型绑定的方法
自定义结构体中可以绑定方法,相同,自定义的数据类型也可以绑定一样的方法type nilstring string func (str nilstring) isNil() { if str == "" { fmt.Println(nil) } else { fmt.Println("not nil") } } func main(){ var str nilstring str.isNil() }
二、方法中的变量传递
1、结构体变量传值
结构体变量传递指针类型变量还是值类型变量,取决于方法定义接收的变量的类型,而不是传递的结构体变量的类型。
例子如下:
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
}
// 接收指针类型的结构体变量
func (p *Person) ToString() string {
str, _ := json.Marshal(p)
return string(str)
}
// 接收值类型的结构体变量
func (p Person) ToString02() string {
str, _ := json.Marshal(p)
return string(str)
}
func main(){
person := other.Person{"张三", 20}
// 传递的person是指针类型
person.ToString()
(&person).ToString()
// 传递的是值类型
person.ToString02()
(&person).ToString02()
}
如上所示,可以清除的看出,结构体变量传递的是值还是指针,取决于方法定义是指定的类型!!!
2、String()方法
直接输出调用结构体变量,会自动寻找自己类型下,是否有String()
方法,如果有直接调用String()方法,没有则按照默认结构体输出!
// 结构体String()方法
func (p *Person) String() string {
str, _ := json.Marshal(p)
return string(str)
}
func main(){
person := other.Person{"张三", 20}
// 直接输出person此时会默认调用String()方法!!!
// 类型必须和String()绑定变量的类型一致!!!
fmt.Println(&person)
}
三、工厂模式的引入
场景:现在一个结构体是私有类型(首字母小写),但是我在别的包下想访问这个结构的数据,想获取结构体中某个字段的值,还想修改字段的值?该怎么做?
这时候工厂模式就派上了用场了
直接上案例:
- 创建
fact.go
type fact struct { name string age int } // 该函数用于构造一个结构体,并且返回该结构体的地址 // 因为结构体是私有的,这里必须返回指针,否则无法使用该内部方法 func NewFact(name string, age int) *fact01 { return &fact01{name, age} } func (f fact) GetName() string { return f.name // return (*f).name } func (f *fact) SetName(name string) { f.name = name // 底层会做优化 =》(*f).name = name }
- 调用
main.go
package main import ( "fmt" other "go_code/package10/other" ) func main(){ fact := other.NewFact("zhangsna", 20) fmt.Println(*fact) fact.SetName("李四") fmt.Println(fact.GetName()) }
四、方法和函数的区别
-
调用方式不一样
函数: 函数名(实参列表)
方法: 变量.函数名(实参列表) -
参数传递不一样
函数: 接收参数类型必须一致,不能将指针类型数据直接传递(接收类型为指针,传参必须为地址),反之亦然。
方法: 变量传递是值传递还是引用传递,取决于,方法定义的变量类型,例如:type struct struct { } func (struct *struct) test1() { } func (struct struct) test2() { } func main(){ // 引用传递 struct.test1() // 引用传递 (&struct).test1() // 值传递 struct.test2() // 值传递 (&struct).test2() }
-
可以粗糙理解为,
函数
是类方法,方法
是实例方法