Golang 语言没有面向对象的概念了,但是可以使用结构体来实现,面向对象编程的一些特性,
例如:继承、组合等特性。
声明一个结构体变量
package main
import "fmt"
type Person struct {
id, age int
name, email string
}
func main() {
var tom Person
fmt.Printf("tom: %v\n", tom)
kite := Person{}
fmt.Printf("kite: %v\n", kite)
}
结构体成员,在没有赋值之前都是零值。
PS E:\TEXT\test> go run .
tom: {0 0 }
kite: {0 0 }
PS E:\TEXT\test>
访问结构体成员
可以使用点运算符(.),来访问结构体成员,例如:
package main
import "fmt"
func main() {
type Person struct {
id, age int
name, email string
}
var tom Person
tom.id = 1
tom.name = "tom"
tom.age = 20
tom.email = "tom@gmail.com"
fmt.Printf("tom: %v\n", tom)
}
PS E:\TEXT\test> go run .
tom: {1 20 tom tom@gmail.com}
PS E:\TEXT\test>
匿名结构体
如果结构体是临时使用,可以不用起名字,直接使用,例如:
package main
import "fmt"
func main() {
var dog struct {
id int
name string
}
dog.id = 1
dog.name = "花花"
fmt.Printf("dog: %v\n", dog)
}
PS E:\TEXT\test> go run .
dog: {1 花花}
PS E:\TEXT\test>
Golang 结构体的初始化
未初始化的结构体,成员都是零值
int 0 flow 0.0 bool false string nil nil
package main
import "fmt"
func main() {
type Person struct {
id, age int
name, email string
}
var tom Person
fmt.Printf("tom: %v\n", tom)
}
PS E:\TEXT\test> go run .
tom: {0 0 }
PS E:\TEXT\test>
使用键值对对结构体进行初始化
package main
import "fmt"
func main() {
type Person struct {
id, age int
name, email string
}
kite := Person{
id: 1,
name: "kite",
age: 20,
email: "kite@gmail.com",
}
fmt.Printf("kite: %v\n", kite)
}
[Running] go run .
kite: {1 20 kite kite@gmail.com}
Golang 结构体作为函数参数
Golang 结构体可以像普通变量一样,作为函数的参数,传递给函数,这里分为两种情况:
- 直接传递结构体,这是一个副本(拷贝),在函数内部不会改变外面结构体内容
- 传递结构体指针,这是在函数内部,能够改变外部结构体内容
直接传递结构体
从运行结果可以看出,函数内部改变了结构体内容,函数外面并没有被改变
package main
import "fmt"
type Person struct {
id int
name string
}
func showPerson(person Person) {
person.id = 1
person.name = "kite"
fmt.Printf("person: %v\n", person)
}
func main() {
person := Person{1, "tom"}
fmt.Printf("person: %v\n", person)
fmt.Println("-------------------")
showPerson(person)
fmt.Println("-------------------")
fmt.Printf("person: %v\n", person)
}
PS E:\TEXT\test> go run .
person: {1 tom}
-------------------
person: {1 kite}
-------------------
person: {1 tom}
PS E:\TEXT\test>
传递结构体指针
package main
import "fmt"
type Person struct {
id int
name string
}
func showPerson(person *Person) {
person.id = 1
person.name = "kite"
fmt.Printf("person: %v\n", person)
}
func main() {
person := Person{1, "tom"}
fmt.Printf("person: %v\n", person)
fmt.Println("-------------------")
showPerson(&person)
fmt.Println("-------------------")
fmt.Printf("person: %v\n", person)
}
PS E:\TEXT\test> go run .
person: {1 tom}
-------------------
person: &{1 kite}
-------------------
person: {1 kite}
PS E:\TEXT\test>
Golang 嵌套结构体
package main
import "fmt"
type Dog struct {
name string
color string
age int
}
type person struct {
dog Dog
name string
age int
}
func main() {
var tom person
tom.dog.name = "花花"
tom.dog.color = "黑白花"
tom.dog.age = 2
tom.name = "tom"
tom.age = 20
fmt.Printf("tom: %v\n", tom)
}
PS E:\TEXT\test> go run .
tom: {{花花 黑白花 2} tom 20}
PS E:\TEXT\test>
Golang 方法
Golang 中的方法,是一种特殊的函数,定义域struct之上(与struct关联、绑定),被称为struct的接受者(receiver)。
通俗的讲,方法就是有接收者的函数。
Golang 语言方法的注意事项
- 方法的 receiver type 并非一定要是 struct 类型,type 定义的类型别名、slice、map、channel、func类型等都可以。
- struct 结合它的方法就等价于面向对象中的类。只不过 struct 可以和它的方法分开,并非一定要属于同一个文件,但必须属于同一个包。
- 方法有两种接收类型:(T Type)和(T *Type),它们之间有区别。
- 方法就是函数,所以Go中没有方法重载(overload)的说法,也就是说同一个类型中的所有方法名必须都唯一。
- 如果 receiver 是一个指针类型,则会自动解除引用。
- 方法和 type 是分开的,意味着实例的行为(behavior)和数据存储(field)是分开的,但是它们通过 receiver 建立起关联关系。
package main
import "fmt"
type Person struct {
name string
}
func (per Person) eat() {
fmt.Println(per.name + " eating....")
}
func (per Person) sleep() {
fmt.Println(per.name + " sleep....")
}
func main() {
var per Person
per.name = "tom"
per.eat()
per.sleep()
}
[Running] go run .
tom eating....
tom sleep....