结构体实例变量
结构体中的方法
type Student struct {
Name string
Age int
Skills []string
}
func (s *Student) Learn(skill string) {
s.Skills = append(s.Skills, skill)
}
func (s *Student) SetName() {
log.Println("修改名字前:" + s.Name)
s.Name = "xiaoming"
log.Println("修改名字后:" + s.Name)
}
func (s Student) SetNameTest() {
log.Println("修改名字前:" + s.Name)
s.Name = "xiaohong"
log.Println("修改名字后:" + s.Name)
}
func main() {
s := Student{}
s.Name = "小刚"
//log.Println(s.Name)
s.SetName()
s.SetNameTest()
log.Println(s.Name)
}
打印结果
2022/04/25 14:16:06 修改名字前:小刚
2022/04/25 14:16:06 修改名字后:xiaoming
2022/04/25 14:16:06 修改名字前:xiaoming
2022/04/25 14:16:06 修改名字后:xiaohong
2022/04/25 14:16:06 xiaoming
可以看出
-
在
func (s Student) SetNameTest()中,接受者为实例变量的副本,在方法内更改值不会影响原来的值 -
在
func (s *Student) SetName()中,接受者为实例变量地址的副本,在方法内更改值会影响原来的值
package中的方法
同理在包中的方法也是一样
func SetName1(s *Student) {
log.Println("修改名字前:" + s.Name)
s.Name = "name1"
log.Println("修改名字后:" + s.Name)
}
func SetName2(s Student) {
log.Println("修改名字前:" + s.Name)
s.Name = "name2"
log.Println("修改名字后:" + s.Name)
}
func main() {
var s Student
s.Name = "小刚"
//log.Println(s.Name)
s.SetName()
s.SetNameTest()
log.Println("-------------分割线-------------")
SetName1(&s)
SetName2(s)
log.Println(s.Name)
}
打印
2022/04/25 14:30:46 -------------分割线-------------
2022/04/25 14:30:46 修改名字前:xiaoming
2022/04/25 14:30:46 修改名字后:name1
2022/04/25 14:30:46 修改名字前:xiaoming
2022/04/25 14:30:46 修改名字后:name2
2022/04/25 14:30:46 xiaoming
结构体的定义
定义结构体的三种方式
var s1 Student // 在内存中直接定义一个结构体变量
s1 := new(Student) // 在内存中直接定义一个结构体变量
var s1 Student // 在内存中直接定义一个结构体变量
构造函数
func NewStudent(name string, age int) *Student { // 返回值指向 Student 结构体的指针
return &Student{
Name: name,
Age: age,
}
}
log.Println("-------------分割线-------------")
s1 := NewStudent("萌新", 123)
log.Println(s1.Name)
log.Println((*s1).Name)
打印
2022/04/25 14:50:28 -------------分割线-------------
2022/04/25 14:50:28 萌新
2022/04/25 14:50:28 萌新
匿名函数
type Class struct {
ClassName string
}
func (cla *Class) OutClassName() {
log.Println("班级名称:" + cla.ClassName)
}
type Student struct {
Name string
Age int
Skills []string
Class
}
log.Println("-------------分割线-------------")
s1 := NewStudent("萌新", 123)
log.Println(s1.Name)
log.Println((*s1).Name)
log.Println("-------------分割线-------------")
s1.ClassName = "1年级"
log.Println(s1.ClassName)
s1.OutClassName()
打印
2022/04/25 15:01:03 -------------分割线-------------
2022/04/25 15:01:03 萌新
2022/04/25 15:01:03 萌新
2022/04/25 15:01:03 -------------分割线-------------
2022/04/25 15:01:03 1年级
2022/04/25 15:01:03 班级名称:1年级
结构体继承结构体,其中被继承结构体的方法全部为继承结构体吸收
组合实现继承
继承
package main
import (
"log"
"strconv"
)
// struct 1
type Person struct {
Name string
}
func (a *Person) Eat() {
log.Println(a.Name + "想吃东西")
}
// struct 3
type Student struct {
*Person
Age int
Skills []string
}
func (s *Student) Eat() {
log.Println(strconv.Itoa(s.Age) + "岁的" + s.Name + "想吃东西")
}
func NewStudent(name string, age int) *Student { // 返回值指向 Student 结构体的指针
return &Student{Person: &Person{name}, Age: age}
}
// 结构体练习
func main() {
log.Println("-------------分割线-------------")
s1 := NewStudent("萌新", 123)
log.Println(s1)
log.Println(s1.Name)
s1.Eat()
log.Println("-------------分割线-------------")
}
打印
2022/04/25 15:38:19 -------------分割线-------------
2022/04/25 15:38:19 &{0xc000010250 123 []}
2022/04/25 15:38:19 萌新
2022/04/25 15:38:19 123岁的萌新想吃东西
参数多态
添加接口
type IPerson interface {
Eat() // 描述吃的行为
}
func StartEat(animal IPerson) {
animal.Eat()
}
// 结构体练习
func main() {
log.Println("-------------分割线-------------")
s1 := NewStudent("萌新", 123)
log.Println(s1)
log.Println(s1.Name)
s1.Eat()
log.Println("-------------分割线-------------")
s := &Person{"老油条"}
StartEat(s)
StartEat(s1)
}
打印
2022/04/25 15:42:21 -------------分割线-------------
2022/04/25 15:42:21 老油条想吃东西
2022/04/25 15:42:21 123岁的萌新想吃东西
接口正在方法的话类也要增加
type IPerson interface {
Eat() // 描述吃的行为
Run()
}
// struct 1
type Person struct {
Name string
}
func (a *Person) Run() {
log.Println("跑步走起")
}
func (a *Person) Eat() {
log.Println(a.Name + "想吃东西")
}