Go_结构体、方法、接口

1. 结构体

1.1 定义结构体

Go语言中没有类的概念,也不支持继承。go中可用结构体来封转多数据类型数据,据说Go语言中结构体的组合方式更具有扩展性和灵活性

type identifier struct{
	field1 type1
	field2 type2
	...
}

type Person struct{
	Name string
	Age int
}

//结构体中字段的类型可以是任何类型,包括函数类型,接口类型,甚至结构体类型本身
type ListNode struct{
	Val int
	Next *ListNode
	string //也可以不指定字段名,这种为匿名字段,一个结构体只能有一个匿名字段
}

1.2 操作结构体
	s1 := new(Person)
	s1.Name= "哈哈"
	s1.string="我是匿名字段赋值"

//必须全字段赋值
	s2 := Person{"zhangsan",32,"remark"}
	//部分字段赋值
	s3 := &Person{
			Name:"lisi",
			Age:33
		}
1.3 标签

go语言中结构体除了字段的名称和类型外还有一个可选的标签tag,标记的tag只有reflect包可以访问到,一般用于orm或者json的数据传递,下面这段代码演示了如何为结构体打标签。

type Person struct {
	Name string `json:"name"`
	Age int 	`json:"age"`	
}

//可以使用go自带的json包将声明的结构体变量转变为json字符串。
func ToJson(p *Person)(string,error){
	bytes, err := json.Marshal(p)
	if err != nil {
		retrun "",nil		
	}
	return string(bytes),nil
}

//如果我们没有给结构体打标签输出的json字符串如下所示
{"Name":"james","Age":35}
//如果我们给结构体打过标签之后输出的json字符串如下所示
{"name":"james","age":35}
1.4 内嵌结构体

结构体作为一种数据类型也可以将其声明为匿名字段,此时我们称其为内嵌结构体。

type A struct {
	X,Y int
}

type B struct {
	A
	Name String
}

//使用
b := new(B)
b.X = 10
b.Y = 20
b.Name = "test"


//嵌套规则
	type A struct{
		X,Y int
	}

	type B struct{
		a A
		Name string
		X int
	}

	type C struct{
		aa A
		b B
		X int
	}

	c := new(C)
	c.aa.X = 10
	c.b.X = 10

2.方法

2.1定义方法

方法与函数类似,只不过在定义方法时会在func 和 方法名之间添加一个参数 (r Receiver)

func (r Receiver)func_name(){
	//body
}

//例子
type Person struct {
	name string
}

func (p Person) GetName() string {
	return p.name
}
func main() {
	p := Person{
		name:"james",
	}
	fmt.Println(p.GetName())
}
2.2 方法接收者

对于一个方法来说接收者分为两种类型:值接收者和指针接收者。上面的GetName的接收者就是值接收者

func (p *Person)SetName(name string){
	p.name = name
}

使用值接收者,在调用的时候使用的其实是值接受者的一个拷贝,所以对该值的任何操作,都不会影响原来的类型变量。
但是如果使用指针接收者的话,在方法体内的修改就会影响原来的变量,在go语言中还有一点比较特殊,我们使用值接收者定义的方法使用指针来调用也是可以的,反过来也是如此

func main(){
	p := &Person{
		name: "james",
	}
	fmt.Println(p.GetName())
	
	p1 := Person{
		name: "james",
	}
	p1.SetName("kobe")
	fmt.Println(p1.GetName())
}

3. 接口

3.1 定义接口

接口相当于一种规范,它需要做的是谁想要实现我这个接口要做哪些内容,而不是怎么做

type Namer interface {
    Method1(param_list) return_type
    Method2(param_list) return_type
    ...
}

//实现接口
type Animal interface {
	Eat()
}

type Bird struct {
	Name string
}

func (b Bird) Eat() {
	fmt.Println(b.Name + "吃虫")
}

type Dog struct {
	Name string
}

func (d Dog) Eat() {
	fmt.Println(d.Name + "吃肉")
}

func EatWhat(a Animal) {
	a.Eat()
}

func main() {
	b := Bird{"Bird"}
	d := Dog{"Dog"}
	EatWhat(b)
	EatWhat(d)
}
3.2 断言

有些时候方法传递进来的参数可能是一个接口类型,但是我们要继续判断是哪个具体的类型才能进行下一步操作,这时就用到了类型断言,下面我们通过一个例子来进行讲解:

func IsDog(a Animal) bool {
	if v, ok := a.(Dog); ok {
		fmt.Println(v)
		return true
	}
	return false
}

func WhatType(a Animal) {
	switch a.(type) {
	case Dog:
		fmt.Println("Dog")
	case Bird:
		fmt.Println("Bird")
	default:
		fmt.Println("error")
	}
}
3.3 空接口

空接口是一个比较特殊的类型,因为其内部没有定义任何方法所以空接口可以表示任何一个类型,

var any interface{}

any = 1
fmt.Println(any)

any = "hello"
fmt.Println(any)

any = false
fmt.Println(any)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值