结构体基础操作

package main

import(
	"fmt"
)

type Cat struct{
	Name string `json:"name"`//返回时 Name会变成name
	Age int
}
func main(){
   //声明方式一
   var cat1 Cat
   cat1.Name ="小白"
   cat1.Age = 21
   fmt.Println(cat1)


   //声明方式二	
   p1 := Cat{"tom",1}
   fmt.Println(p1)


   //声明方式三 指针方式
   var p3 *Cat = new(Cat)
   //因为p3是一个指针,因此标准的给字段赋值方式
   (*p3).Name = "小迪"
   (*p3).Age = 12
   fmt.Println(*p3)
   //底层代码所以 (*p3).Name = "小迪" 等同于 p3.Name = "小迪" 这种写法


   //声明方式四 同方式三一样可以简写 
   // (*person).Name = "小幂" 等价于  person.Name = "小幂"
   var person *Cat = &Cat{}
   (*person).Name = "小幂"
   (*person).Age = 38
   fmt.Println(*person)
}

结构体是 值类型

package main
import(
	"fmt"
)
/*
 type (结构体名称) struct{
   field1 type
   field2 type
 }
*/

type Cat struct{
	Name string
	Age int
	Color string
}
func main(){
    var cat1 Cat
	cat1.Name = "小白"
	cat1.Age = 10
	cat1.Color = "白色"
	fmt.Println("猫的名称:",cat1.Name)
	fmt.Println("猫的年龄:",cat1.Age)
	fmt.Println("猫的颜色:",cat1.Color)
	/*
	结果
	猫的名称: 小白
	猫的年龄: 10  
	猫的颜色: 白色
	*/
}
package main
import(
	"fmt"
)
//如果结构体的字段类型时:指针,slice,和map的零值都是nil,即还没有分配空间
//如果需要使用这样的字段,需要先make,才能使用

type Person struct{
	Name string
	Age int
	Socres [5]float64 //数组
	Ptr *int //指针
	Slice []int //切片
	Map1 map[string]string //map
}

type Monster struct{
	Name string
	Age int
}

func main(){
	var p1 Person
	fmt.Println(p1)

	
	p1.Socres[0] = 126
	fmt.Println(p1)


	//先make后才能赋值 否则会提示没有空间
	p1.Slice = make([]int,2)
	p1.Slice[0] = 1
	fmt.Println(p1)

	p1.Map1 = make(map[string]string)
	p1.Map1["tom"] = "many"
	fmt.Println(p1)


	//不同结构体遍历的字段是独立的,互不影响
	//不影响另外一个,结构体是值类型
    var monster1 Monster
	monster1.Name = "牛魔王"
	monster1.Age = 120

	monster2 := monster1
	monster2.Name = "铁扇公主"
	fmt.Println("monster1 = ",monster1)//monster1 =  {牛魔王 120}
	fmt.Println("monster2 = ",monster2)//monster2 =  {铁扇公主 120}

	//如果需要改变的话,可以加一个&引用符
	//	monster2 := &monster1

}

使用案例一:

给Person结构体 添加 speak 方法,输出 xxx是一个好人

package main

import(
	"fmt"
)
type Person struct{
	Name string `json:"name"`
}

func (person Person) speak(){
	fmt.Println(person.Name,"是一个好人")
}
func main(){
     var p Person
	 p.Name = "tom"
	 p.speak()
	 
}

使用案例二:

给 Person 结构体添加 jisuan 方法,可以计算 从 1++1000的结果

package main

import(
	"fmt"
)
type Person struct{
    Name string
}

func (person Person) jisuan(){
	res := 0
	for i := 1; i <= 1000; i++{
		res += i
	}
	fmt.Printf("%v 计算 1-1000相加的结果为:%v",person.Name,res)
}
func main(){
     var p Person
	 p.Name = "toms"
	 p.jisuan()
	 
}

使用案例三:
给 Person 结构体 jisuan2 方法,该方法可以接收一个数n,计算从1+ +n的结果

给结构体传参

package main

import(
	"fmt"
)
type Person struct{
    Name string
}

func (person Person) jisuan2(n int){
	res := 0
	for i := 1; i <= n; i++{
		res += i
	}
	fmt.Printf("计算 1-%v相加的结果为:%v",n,res)
}
func main(){
     var p Person
	 p.jisuan2(10)
	 
}

使用案例四:

给Person结构体添加getSum方法,可以计算俩个数的和,并返回结果

package main

import(
	"fmt"
)
type Person struct{

}

func (person Person) getSum(n1,n2 int) int {
	return  n1 + n2
}
func main(){
     var p Person
	 res := p.getSum(10,20)
	 fmt.Println(res)
}

封装:

golang语言中没有 构造方法,可以以工厂模式来代替构造方法

package model
import(
	"fmt"
)

type account struct{
	accountNo string
	pwd string
	balance float64
}

func NewAccount(account1 string,pwd string,balance float64) *account {
	if len(account1) < 6 || len(account1) > 10 {
		fmt.Println("账号长度不正确。。。")
		return nil
	}

	if len(pwd) != 6 {
		fmt.Println("密码长度不正确。。。")
		return nil
	}

	
	if balance < 20 {
		fmt.Println("余额数目不正确。。。")
		return nil
	}
	return &account{
		accountNo : account1,
		pwd : pwd,
		balance : balance,
	}
}


//赋值
func (account *account) SetAccount(accountNo string){
	account.accountNo = accountNo
}

//取值
func (account *account) GetAccount() string{
	return account.accountNo
}
package main
import(
	"fmt"
	"go_code/project01/object/demo11/model"
)

func main(){
	account := model.NewAccount("cs0001","123456",600)
	account.SetAccount("ce0003")
	if account != nil {
		fmt.Println("创建成功=",*account,account.GetAccount())
	} else {
		fmt.Println("创建失败")
	}
    //结果 创建成功= {ce0003 123456 600} ce0003

}

继承:

只要继承父级结构体不管 属性首字母大小写都可以使用

package main

import(
	"fmt"
)
//父级结构体
type Student struct{
    Name string
	Age int
	Score int
}
//查询信息
func (stu *Student) ShowInfo(){
	fmt.Printf("学生名=%v 年龄=%v 成绩=%v\n",stu.Name,stu.Age,stu.Score)
}

//添加成绩
func (stu *Student) SetStudent(score int){
	stu.Score = score
}

//子级结构体
type Puiil struct{
	Student //嵌入匿名结构体
}

func (p *Puiil) testing(){
	fmt.Println("小学生正在考试中。。。。。。。。。。")
}

//子级结构体
type Graduate struct{
	Student //嵌入匿名结构体
}

func (p *Graduate) testing(){
	fmt.Println("大学生正在考试中。。。。。。。。。。")
}

func main(){
	p := Puiil{}
	p.Student.Name = "tom"
	p.Student.Age = 18
	p.testing()
	p.Student.SetStudent(60)//调用父级结构体方法
	p.Student.ShowInfo()
	/*
	小学生正在考试中。。。。。。。。。。
    学生名=tom 年龄=18 成绩=60
	*/
    /*
    上面调用方式可以简写
    p.Name = "tom"
	p.Age = 18
	p.testing()
	p.SetStudent(60)//调用父级结构体方法
	p.ShowInfo()
    编译器先看Puiil结构里面是否有对于属性或者方法,如果没有就去看Puiil 嵌入的匿名Student结构体 
    如果有 就调用,如果没有就会看Student结构体有没匿名嵌套 ,如果没有就一直往上 查找直到
    如果找到没有属性或方法时才会提示错误
    
    当前结构体和继承结构体中出现相同的属性或者方法时就会执行就近原则
    继承多个结构体时都存在相同属性或方法时必须带上前缀
    */

	g := Graduate{}
	g.testing()
	g.Student.SetStudent(90)
	g.Student.ShowInfo()
	/*
	大学生正在考试中。。。。。。。。。。
	学生名= 年龄=0 成绩=90
	*/


    /*
     简写
   	p := Puiil{}
	p.Student.Name = "tom"
	p.Student.Age = 18
    下面这俩种方式等同于上面的写法
     
	p := Puiil{Student{"tom",11,56}}
	p1 := Puiil{
		Student{
			Name : "tom",
			Age : 11,
			Score : 56,
		},
	}
    */
}