一、基本说明:

Golang 中的方法是作用在指定的数据类型上的(即:和指定的数据类型绑定),因此自定义类型, 都可以有方法,而不仅仅是 struct。也就是方法可以在任意数据类型上面定义。

方法定义的语法:

func (变量名 type) 方法名(参数列表) (返回值列表){
     //方法体 
     return 返回值 
 }

示例如下:

type Student struct {
    Name string
    Age int
}
// 定义方法,只能Student类型的实例调用。//这里 s 变量相当于其他语言的this。
func (s Student) test() {
    fmt.Println(s) // {张三 20}
}

func main() {
    var stu  = Student{"张三",20}
    stu.test() //调用test() 方法
}

说明:

1、func (s Student) test(){ //方法体 } 这里的 (s Student) 表示给Student类型绑定了一个方法test()。并且变量名 s 可以在方法体内使用。

2、s 变量就是调用这个方法的实例作为参数传递进来,也区分值传递、引用传递。struct是值传递。所以s是一个拷贝。和函数传递参数特征一样。

1.1.1. 二、示例2:给Student类型添加一个求和方法。

type Student struct {
    Name string
    Age int
}
//给Student绑定一个求和方法 add 。
func (s Student) add(n1 int, n2 int) int {
    return n1 + n2
}

func main() {
    var stu  = Student{"张三",20}

    sum := stu.add(10, 90) //调用方法

    fmt.Println(sum) // 100
}

1.1.2. 三、使用方法的注意事项。

1、如果给结构体绑定方法,希望在方法中修改调用这个方法的实例的属性值,可以传递指针。

实际操作中如果给结构体struct绑定方法,因为struct是值类型,传参和变量赋值是拷贝,因此更多的是传递struct指针,防止拷贝。

type Student struct {
    Name string
    Age int
}
//给Student绑定一个modify()方法。
func (s *Student) modify() {
    s.Name = "wang5" //改变name的值 等价于 (*s).Name = "wang5"
}

func main() {
    var stu  = Student{"张三",20}
    //调用方法
    stu.modify() //等价于 (&stu).modify()

    fmt.Println(stu) // {wang5 20}  方法内修改影响了外部变量stu
}

说明:

stu.modify() 等价于 (&stu).modify()

s.Name = "wang5" 等价于 (*s).Name = "wang5"

这个是编译器底层做优化实现的。

2、自定义类型都可以有方法,而不仅仅是 struct, 比如 int , float32 等都可以有方法。

type Myint int

// 给 Myint 类型绑定方法
func (num Myint) test() {
    fmt.Println(num) //9

}
func main() {
    var num1 Myint = 9
    num1.test()
}

其实type Myint int 就是定义了一种新的类型Myint,给自定义类型加方法是可以的。

3、方法名首字母小写,只能在本包访问;方法首字母大写,可以在本包和其它包访问。

4、如果一个类型实现了 String()这个方法,那么 fmt.Println 默认会调用这个变量的 String()进行输出。

type Student struct {
    Name string
    Age int
}

func (stu Student) String() string  {
    str := fmt.Sprintf("name = %v,age = %v",stu.Name,stu.Age)
    return str
}
func main() {
    s := Student{"张三",12}

    // 自动调用Student类型的String()方法
    fmt.Println(s) //name = 张三,age = 12
}

1.1.3. 四、方法和函数区别。

1、调用方式不一样。

  • 函数的调用方式: 函数名(实参列表)

  • 方法的调用方式:变量.方法名(实参列表)

2、方法前面的绑定类型,可以是某类型或者他的指针类型。调用的时候可以使用这个类型的实例或指针调用。(仅限方法前面的绑定类型,函数的参数、方法后面的参数需要保持参数类型严格一致。)

例如如下:无论方法直接绑定某类型,还是它的指针类型,都可以使用这个类型的实例或指针直接调用。

type Student struct {
    Name string
}
// 绑定指针类型 *Student
func (s *Student) test1() {
    fmt.Println("test1.....")
}

// 绑定类型 Student
func (s Student) test2() {
    fmt.Println("test2.....")
}

func main() {
    var stu = Student{"张三"}
    stu.test1() // 调用成功
    (&stu).test1() // 调用成功

    stu.test2() // 调用成功
    (&stu).test2() // 调用成功
}

注意:无论怎么调用,因为Student 是struct。所以(s *Student) 都是引用传递,(s Student) 都是值拷贝。

3、特别注意一点。无论任何地方,都可以使用指针名点变量获取到属性的值。

type Student struct {
    Name string
}
func (s *Student) test1(s2 *Student) {
    var name string = s2.Name; // 取得学生名
    fmt.Println("test1.....",name)
}
func test2(s *Student) {
    var name string = s.Name; // 取得学生名
    fmt.Println("test2.....",name)
}
func main() {
    var stu = Student{"张三"}

    var name string = (&stu).Name
    fmt.Println(name) //张三

    stu.test1(&stu)
    test2(&stu)
}

上面例子中,main方法内使用(&stu).Name 获得属性值。方法test1、函数test2 的指针参数点Name都可以获取属性值。

results matching ""

    No results matching ""