八. Go学习:结构体的工厂模式、tag的使用、匿名字段和方法

本文总结了结构体的工厂模式、tag的使用、匿名字段和方法

目录

struct的工厂模式

struct中tag的使用

匿名字段

方法


struct的工厂模式

Go中的struct无构造函数,我们可通过工厂模式初始化

package main

import "fmt"

//工厂模式,Go中无构造函数,我们用工厂模式代替
type student struct {
	Name string
	Age  int
}
func NewStudent(name string, age int) *student {
	return &student{
		Name: name,
		Age:  age,
	}
}
func main() {
	S := new(student)
	S = NewStudent("tony", 20)
	fmt.Println(S)
}

struct中tag的使用

我们可以为struct中的每个字段,写上一个tag。这个tag可以通过反射的机制获得,最常用的场景就是json序列化和反序列化。如下面代码所示,因为结构体中均为小写开头,json序列化后输出的结果为空,用大写则正常。那么我们要用小写怎么办呢?此时tag可发挥作用了

package main

import (
	"encoding/json"
	"fmt"
)
type Student struct {
	name  string
	age   int
	score int
}
func main() {
	var stu Student = Student{
		name:  "stu01",
		age:   18,
		score: 80,
	}
	data, err := json.Marshal(stu)
	if err != nil {
		fmt.Printf("json encode stu faild,error")
		return
	}
	fmt.Println(string(data))
}

  

我们加入tag后,虽然结构体中为大写,但如下输出结果图所示,用tag后json打包的均为小写

type Student struct {
	Name  string `json:"name"`
	Age   int    `json:"age"`
	Score int    `json:"score"`
}

   

匿名字段

结构体中字段可以没有名字,即匿名字段。匿名字段的访问如下代码所示:

注:匿名字段里实现了继承

package main

import (
	"fmt"
	"time"
)

type Cart struct {
	name string
	age  int
}
type Train struct {
	Cart
	int
	start time.Time
}

func main() {
	var t Train      //匿名字段的访问
	t.Cart.name = "train" //可直接访问Cart结构体中的name和age
	t.Cart.age = 100
	t.int = 200
	fmt.Println(t)
}

  

方法

Go中的方法是作用在特定类型的变量上,因此自定义类型都可以有方法,而不仅仅是struct。其定义为:func (receiver type) methodName(参数列表)(返回值列表){}。其中,我们是通过(recevier type)来访问type中的字段。在C++中,此会定义在结构体里面,然后public。

package main

import "fmt"

type Student struct {
	Name  string
	Age   int
	Score int
}
func (p Student) init(name string, age int, score int) {
	//通过(p Student)访问Student中的字段
	//在C++中会定义在结构体里面,然后public
	p.Name = name
	p.Age = age
	p.Score = score
	fmt.Println(p)
}
func (p Student) get() Student {
	return p
}
func main() {
	var stu Student
	stu.init("stu", 10, 200)
	stu1 := stu.get()
	fmt.Println(stu1)
}

此时,输出结果如下:但我们会发现一个问题,就是init没有生效。原因为:此时的p仅仅为stu的一个拷贝,解决此问题,我们得传进一个指针。

  

用指针换用如下代码即可

package main

import "fmt"

type Student struct {
	Name  string
	Age   int
	Score int
}
func (p *Student) init(name string, age int, score int) {
	//通过(p Student)访问Student中的字段
	//在C++中会定义在结构体里面,然后public
	p.Name = name
	p.Age = age
	p.Score = score
	fmt.Println(p)
}
func (p Student) get() Student {
	return p
}
func main() {
	var stu Student
	stu.init("stu", 10, 200)
	stu1 := stu.get()
	fmt.Println(stu1)
}

方法用于其他类型:

package main

import "fmt"

type integer int
func (p integer) print() {
	fmt.Println("p is", p)
}
func (p integer) set(b integer) {    //非指针
	p = b
}
func (p *integer) set1(b integer) {   //指针
	*p = b
}

func main() {
	var a integer
	a = 100
	a.print()
	a.set(1000)
	a.print()       //输出仍然为100
	a.set1(1000)
	a.print()       //输出为1000
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值