Go语言之结构体

一、结构体

1.Golang并不是纯粹的面向对象语言,但支持面向对象特性
2.Golang中没有class,结构体struct与其他语言的class同等地位
3.Golang面向对象非常简洁,去掉传统的方法重载,构造函数,隐藏this指针等
4.Golang中面向接口编程非常重要,耦合性低
5.结构体是值类型,结构体是自定义数据类型,结构体变量是具体的实际的变量
6.结构体字段如果是指针、slice、map默认零值是nil,即没有分配空间,使用时一定要先make

package main

import (
	"encoding/json"
	"fmt"
)

//结构体声明,字段在内存中的地址是连续的
type Person struct { //每次type都是重新定义一次,相当于新的数据类型,但可以强转
	Name   string `json:"name"`
	Age    int
	Scores [3]float64
	ptr    *int              //默认nil
	slice  []int             //默认nil
	map1   map[string]string //默认nil
}

func main() {
	//创建结构体实例第一种方式
	var person Person //var a int
	person.Name = "小红"
	person.Age = 13
	fmt.Println(person)
	fmt.Println("人的名字:", person.Name)
	//第二种方式
	p2 := Person{"小王", 15, [3]float64{88, 98, 99}, nil, nil, nil}
	pp2 := Person{Name : "小王",Age:15} //不依赖字段定义顺序
	fmt.Println(p2)
	//第三种方式
	p3 := new(Person) //p3是一个结构体指针
	(*p3).Name = "小张" //标准赋值方法
	p3.Name = "小赵"    //这样也可以,因为go设计者为了程序员方便,底层进行了处理
	(*p3).Age = 16
	fmt.Println(*p3)
	fmt.Println((*p3).Age) //()必须加,因为"."运算符优先级高
	//第四种方式
	p4 := &Person{} //p4是一个结构体指针
	(*p4).Name = "小刘"
	p4.Name = "小关" //与第三种方式一致
	(*p4).Age = 18
	fmt.Println(*p4)//因为是指针所以要取值运算符

	//使用tag标签,使json字段变成小写
	jsonStr, _ := json.Marshal(person)
	fmt.Println(string(jsonStr))
	
	//工厂模式,结构体在model包中访问私有变量
	var student = model.NewStudent("Tom", 19)
	fmt.Println(*student)
	fmt.Println(student.GetName())
}

package model

type student struct {
	name string
	age  int
}

func NewStudent(n string, a int) *student {
	return &student{n, a}
}

func (s *student) GetName() string {
	return s.name
}

二、方法

package main

import "fmt"

type Person struct {
	Name string
	Age  int
}

//表示Person类型绑定一个test方法
//p 是一个实例
func (p Person) test() { //person调用此函数,person进行拷贝,值拷贝
	p.Name = "小王"
	fmt.Println(p.Name)
}

func (p *Person) test01() { 
	p.Name = "Jack"
	fmt.Println(p.Name)
}

func (p *Person) String() string {
	//编译器底层做了处理 p.Name 等价于 (*p).Name
	str := fmt.Sprintf("Name=%v,Age=%v", p.Name, p.Age)
	return str
}
func main() {
	var person Person
	person.Name = "小张"
	person.Age = 15
	
	//决定是值拷贝还是地址拷贝是看方法和哪个类型绑定
	person.test()
	(&person).test()    // 编译器特殊处理,本质上也是值拷贝
	fmt.Println(person) //输出小张

	person.test01()    //等价于(&person).test01(),编译器特殊处理
	(&person).test01() //正常调用方式
	fmt.Println(person) //输出 Jack
	
	//如果重写了指针类型 *Person 的 String() 方法,就会自动调用。
	fmt.Println(&person) //自动调用 String()
	//标准 (&person).String(),但编译器底层做了处理
	str := person.String()
	fmt.Println(str)
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值