1、快速入门–以面向对象方式解决养猫问题(struct)
package main
import "fmt"
//定义一个Cat结构体,将Cat的各个字段/属性信息放入带Cat结构体进行管理
type Cat struct {
Name string
Age int
Color string
Hobby string
}
func main() {
//创建一个Cat变量
var cat1 Cat
cat1.Name="tom"
cat1.Age=10
cat1.Color="灰色"
cat1.Hobby="吃"
fmt.Println("cat1=",cat1)
fmt.Println("猫的信息如下:")
fmt.Println("name=",cat1.Name)
fmt.Println("Age=",cat1.Age)
fmt.Println("color=",cat1.Color)
fmt.Println("hobby=",cat1.Hobby)
}
2、结构体和结构体变量(实例)的区别和联系
通过上面的案例我们可以看出:
(1)结构体是自定义的数据类型,代表一类事物.
(2)结构体变量(实例)是具体的,实际的,代表一个具体变量
3、如何声明一个结构体
基本语法
type 结构体名称 struct{
field1 type
field2 type
}
举例
type Student struct {
Name string //字段
Age int
Score float32
}
字段注意事项和细节说明
(1)字段声明语法同变量,示例:字段名 字段类型
(2)字段的类型可以为:基本类型、数组或引用类型
(3)在创建一个结构体变量后,如果没有给字段赋值,都对应一个零值(默认值),规则同 前面讲的一样。
布尔类型是false,数值是0,字符串是"。 数组类型的默认值和它的元素类型相关,比如score [3]int则为[0, 0, 0] 指针,slice, 和map的零值都是nil ,即还没有分配空间。
案例演示
package main
import "fmt"
//定义一个Cat结构体,将Cat的各个字段/属性信息放入带Cat结构体进行管理
type Cat struct {
Name string
Age int
Scores [5]float64
ptr *int //指针
slice []int //切片
map1 map[string]string //map
}
func main() {
//创建一个Cat变量
var cat1 Cat
fmt.Println("cat1=", cat1)
if cat1.ptr == nil {
fmt.Println("ok1")
}
if cat1.slice == nil {
fmt.Println("ok2")
}
if cat1.map1 == nil {
fmt.Println("ok3")
}
//使用slice时一定要make
cat1.slice = make([]int, 10)
cat1.slice[0] = 100 //ok
//使用map时要先make
cat1.map1 = make(map[string]string)
cat1.map1["key1"] = "tom1"
fmt.Println(cat1)
}
运行结果
(4)不同结构体变量的字段是独立,互不影响,一个结构体变量字段的更改,不影响另外一个结构体,结构体是值类型。
案例演示
type Monster struct {
Name string
Age int
}
func main() {
var monster1 Monster
monster1.Name = "牛魔王"
monster1.Age = 100
monster2 := monster1 //结构体是值类型,默认为值拷贝
monster2.Name = "青牛精"
fmt.Println("monster1=", monster1) //monster1= {牛魔王 100}
fmt.Println("monster2=", monster2) //monster2= {青牛精 100}
}
4、创建结构体变量和访问结构体字段
方式1——直接声明
var person Person
方式2——{}
type Person struct {
Name string
Age int
}
var person Person = Person{}
//p2.Name = "tom"
//p2.Age = 20
p2 := Person{"mary",20}
方式3——&
var person *Person = new(Person)
type Person struct {
Name string
Age int
}
func main() {
var p3 *Person = new(Person)
//因为p3是一个指针,因此标准的给字段赋值方式
// (*p3).Name="smith",也可以这样写p3.Name="smith"
//当对p3.Name="smith"进行赋值时,golang的底层会给p3加上取值运算(*p3).Name="smith"
(*p3).Name = "smith"
//p3.Name = "join"
(*p3).Age = 10
//p3.Age = 100
fmt.Println(p3)
}
方式4——{}
var person *Person = &Person{}
type Person struct {
Name string
Age int
}
func main() {
//var person *Person = &Person{"mary",10}
var person *Person = &Person{}
//因为person 是一个指针,因此标准的给字段赋值方式
// (*person).Name="smith",也可以这样写person .Name="smith"
//当对person .Name="smith"进行赋值时,golang的底层会给person 加上取值运算(*person ).Name="smith"
//下面的语句一可以直接给字段赋值
(*person).Name = "smith1"
//person.Name = "join1"
(*person).Age = 101
//person.Age = 100
fmt.Println(person)
}
说明:
(1)第3种和第4种方式返回的是结构体指针。
(2)结构体指针访问字段的标准方式应该是:(*结构体指针).字段名,比如(*person).Name = “tom”
(3)但go做了一个简化,也支持结构体指针字段名, 比如person.Name = “tom”.更加符合程序员使用的习惯,go编译器底层对person.Name做了转化(*person).Name。
5、方法
在某些情况下,我们要需要声明(定义)方法。比如Person结构体:除了有一些字段外(年龄,姓名…),Person结构体还有一些行为,比如:可以说话、跑步…通过学习,还可以做算术题。这时就要用方法才能完成。
Golang中的方法是作用在指定的数据类型.上的(即:和指定的数据类型绑定),因此自定义类型,都可以有方法,而不仅仅是struct.
(1)方法的声明和调用
type A struct {
Num int
}
func (a A) test() {
fimt.Println(a.Num)
}
➢对上面的语法的说明
- func(a A) test() {} 表示A结构体有一方法,方法名为test
- (a A) 体现test 方法是和A类型绑定的
案例演示
type Person struct {
Name string
Age int
}
//给Person绑定一个方法
func (p Person) test() {
fmt.Println("test() name=", p.Name)
}
func main() {
var p Person
p.Name = "tom"
p.test() //调用方法
}
➢对上面的总结
- test 方法和Person类型绑定
2)test方法只能通过Person类型的变量来调用,而不能直接调用,也不能使用其它类型变量来调用
方法快速入门
(1)给Person结构体添加sum1方法,可以计算从1+…+1000 的结果,说明方法体内可以函数一样,进行各种运算
func (p Person) sum1() {
res := 0
for i:=1;i<1000;i++ {
res+=i
}
fmt.Println(p.Name,"计算的结果为=",res)
}
(2)给Person结构添加sum2方法,该方法可以接收一个数n,计算从1+…+n的结果
func (p Person) sum2(n int) {
res := 0
for i:=1;i<n;i++ {
res+=i
}
fmt.Println(p.Name,"计算的结果为=",res)
}
func main() {
var p Person
p.sum1()
p.sum2(100)
}
(3)给Person结构体添加getSum方法,可以计算两个数的和,并返回结果
func (p Person) getSum(n1 int, n2 int) int {
return n1 + n2
}
func main() {
var p Person
res:=p.getSum(10,20)
fmt.Println(res)
}
案例1
请编写-一个程序,要求如下:
1)声明一个结构体Circle, 字段为radius
2)声明一个方法area和Circle绑定,可以返回面积。
type Circle struct {
radius float64
}
func (c Circle) area() float64 {
return 3.14 * c.radius * c.radius
}
func main() {
var c Circle
c.radius = 5.0
area := c.area()
fmt.Println("面积为=", area)
}