1、结构体声明
type 结构体名称 struct{ field type field type }
举例:
type Dog struct { Name string Age int Color string }
2、结构体使用
2.1 直接声明
var dog Dog
2.2 {}
type Dog struct { Name string Age int Color string } func main() { dog := Dog{"来福", 3, "白色"} fmt.Printf("dog=%v\n", dog) }
2.3 new()
type Dog struct { Name string Age int Color string } func main() { dog := new(Dog) // dog是一个指针,因此标准的给字段赋值应该是(*dog).Name = "来福" (*dog).Age = 3 (*dog).Color = "白色" // go设计者为了程序员使用方便,底层会对dog.Name = "来福"进行处理,会给dog加上取值运算(*dog).Name = "来福" dog.Name = "来福" // 等价于(*dog).Name = "来福" dog.Age = 3 // 等价于(*dog).Age = 3 dog.Color = "白色" // 等价于(*dog).Color = "白色" fmt.Printf("dog=%v\n", *dog) }
2.4 &
type Dog struct { Name string Age int Color string } func main() { dog := &Dog{"来福", 3, "白色"} fmt.Printf("dog=%v\n", *dog) }
2.5 创建struct实例指定字段值
type Person struct { Name string Age int } func main() { person := Person{ Name: "Tom", Age: 18, } personPor := &Person{ Name: "Jack", Age: 20, } fmt.Println("person=", person) fmt.Println("personPor=", *personPor) }
第三种方式和第四种方式返回的是结构体指针,结构体指针访问字段的标准方式应该是:(*结构体指针).字段名,比如(*dog).Name = "来福"
3、方法的声明
func (recevier type) methodName(参数列表)(返回值列表){ 方法体 return 返回值 }
参数列表,表示方法输入
recevier type:表示这个方法和type这个类型进行绑定,或者说该方法作用于type类型
recevier type:可以是结构体,也可以说是自定义类型。
recevier就是type类型的一个变量(实例)。
参数列表表示方法的输入
返回值列表,表示返回的值,可以是多个。
方法主体,表示为了实现某一功能代码块
return语句不是必须的
type Dog struct { Name string Age int Color string } // 给Dog类型绑定一个方法 func (d Dog) Eat(food string) { fmt.Printf("%v正在吃%v\n", d.Name, food) } func main() { d := Dog{ Name: "小花", Age: 3, Color: "花色", } // 调用方法 d.Eat("骨头") }
4、函数和方法的区别
调用方式不一样
函数的调用方式:函数名(实参列表)
方法的调用方式:变量.方法名(实参列表)
b. 对于普通函数,接收者是值类型时,不能将指针类型的数据直接传递
c. 对于方法(如struct的方法),接收者为值类型时,可以直接用指针类型的变量调用方法
type Person struct { Name string Age int } func (p Person) test() { p.Name = "Merry" } func (p *Person) test01() { p.Name = "Jack" } func main() { person := Person{ Name: "Tom", Age: 18, } person.test() fmt.Println("name=", person.Name) (&person).test() // 从形式上是传入地址,但本质任然是值拷贝 fmt.Println("name=", person.Name) person.test01() // 等价于(&person).test01() 从形式上是传入值类型,但本质任然是地址拷贝 fmt.Println("name=", person.Name) (&person).test01() fmt.Println("name=", person.Name) }
输出:
name= Tom name= Tom name= Jack name= Jack
不管调用形式如何,真正决定是值拷贝还是地址拷贝,看这个方法是和那个类型绑定的
如果是和值类绑定型,比如: (p Person) test(),则是值拷贝
如果是和地址类型绑定,比如:func (p *Person) test01(),则是地址拷贝