Golang 结构体

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....