小小程知识库 小小程知识库
首页
Golang
MySQL
归档
GitHub (opens new window)

xxcheng

记录美好生活~
首页
Golang
MySQL
归档
GitHub (opens new window)
  • 语言基础

  • GORM 框架

  • go-zero 微服务

  • 专题学习

  • 未整理的学习笔记

    • golang夯实基础第一天
    • golang夯实基础第二天
    • golang夯实基础第三天
    • golang夯实基础第四天
    • golang夯实基础第五天
    • golang夯实基础第六天
    • golang夯实基础第七天
    • golang夯实基础第八天
      • 匿名字段
      • 接口 interface
        • 定义
        • 基本格式
        • 基本示例
        • 接收者类型不同对接口实现的区别
        • 值类型接收者
        • 指针类型接收者
        • 一个类型对应多个接口
        • 多个类型对应一个接口
        • 接口嵌套
        • 空接口
        • 应用场景
        • 接收参数
        • 值为任意类型的键值对 map
  • Golang
  • 未整理的学习笔记
xxcheng
2023-07-10
目录

golang夯实基础第八天

# 面向对象

# 匿名字段

见匿名嵌套结构体 (opens new window)

# 接口 interface

定义对象方法的规范,只定义规范,具体实现由对应的对象实现,在 Go1.18 之前,接口只定义方法,只有方法集(method set),在 Go1.18 版本出现了泛型,接口同时也转变为了类型集(type Set),可以用于定义类型。

在这里先按照 Go1.18 之前的版本进行学习归纳,在后面再对泛型进行学习之后,再学习归纳接口对类型的定义规范。

# 定义

  • 接口是一个或多个方法定义的集合;
  • 任何类型只要实现了接口定义的全部的方法集,那么它就实现了该接口;
  • 实现接口的方法指的是方法名相同,接收参数、数据类型相同,返回值参数、数据类型相同;
  • 任何数据类型都实现了 interface{} 这个 空接口;
  • Go 的接口在命名时,一般会在单词后面添加 er,比如 Writer;
  • 一个类型可以实现一个或多个接口,多个类型可以实现同一个接口;
  • 接口和接口之间可以实现嵌套;

# 基本格式

 type 接口类型名 interface{
     方法名1( 参数列表1 ) 返回值列表1
     方法名2( 参数列表2 ) 返回值列表2
     // …
 }
1
2
3
4
5
type Person interface {
	Walk()
	Say()
}
1
2
3
4

# 基本示例

a.go

package day08

import "fmt"

type Person interface {
	Walk()
	Say()
}
type Student struct {
	Name string
	Age  int
}

func (s Student) Walk() {
	fmt.Println("学生", s.Name, "正在走路...")
}
func (s Student) Say() {
	fmt.Println("学生", s.Name, "正在说话...")
}

type Man struct {
	Name string
	Age  int
}

func (m Man) Walk() {
	fmt.Println("男人", m.Name, "正在走路...")
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

运行 Test_01 单元测试

func Test_01(t *testing.T) {
	s := Student{"xxcheng", 18}
	var a Person = s
	a.Walk()
}
1
2
3
4
5
[root@CentOS day08]# go test -run Test_01
学生 xxcheng 正在走路...
PASS
ok      day08   0.002s
1
2
3
4

Student 实现了 Person 接口定义的两个方法,所以实现了 Person 接口,所以可以将定义好的变量 s 赋值给类型为 Person 的变量 a ,可以运行成功

运行 Test_02 单元测试

func Test_02(t *testing.T) {
	m := Man{"xxcheng", 18}
	var a Person = m
	a.Walk()
}
1
2
3
4
5
[root@CentOS day08]# go test -run Test_02
# day08 [day08.test]
./a_test.go:12:17: cannot use m (variable of type Man) as Person value in variable declaration: Man does not implement Person (missing method Say)
FAIL    day08 [build failed]
1
2
3
4

Man 只实现了 Person 接口的 Walk 方法,没有 Person 接口,所以无法将定义好的变量 m 赋值给类型为 Person 的变量 a ,不能运行成功

# 接收者类型不同对接口实现的区别

先定义一个 Run 接口和一个 Dog 结构体

type Run interface {
	Run()
}
type Dog struct {
}
1
2
3
4
5

# 值类型接收者

func (d Dog) Run() {
	fmt.Println("狗跑...")
}
1
2
3
func Test_03(t *testing.T) {
	var r Run
	d := Dog{}
	d2 := &Dog{}
	fmt.Printf("%T,%T\n", d, d2)
	r = d
	fmt.Printf("%T\n", r)
	r = d2
	fmt.Printf("%T\n", r)
}
1
2
3
4
5
6
7
8
9
10
[root@CentOS day08]# go test -run Test_03
day08.Dog,*day08.Dog
day08.Dog
*day08.Dog
PASS
ok      day08   0.002s
1
2
3
4
5
6

接收者为值类型时,实现 Run 接口的是 Dog 类型和 *Dog 类型

# 指针类型接收者

func (d *Dog) Run() {
	fmt.Println("狗跑...")
}
1
2
3
[root@CentOS day08]# go test -run Test_03
# day08 [day08.test]
./a_test.go:34:6: cannot use d (variable of type Dog) as Run value in assignment: Dog does not implement Run (method Run has pointer receiver)
FAIL    day08 [build failed]
1
2
3
4

image-20230708151405160

接收者为指针类型时,实现 Run 接口的只有 *Dog 类型

可以参考方法-方法集 (opens new window)

# 一个类型对应多个接口

type A interface {
	a()
}
type B interface {
	b()
}

type C struct {
}

func (c C) a() {
	fmt.Println("aaa...")
}
func (c C) b() {
	fmt.Println("bbb...")
}

func Test_04(t *testing.T) {
	c := C{}
	var x A = c
	var y B = c
	x.a()
	y.b()
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[root@CentOS day08]# go test -run Test_04
aaa...
bbb...
PASS
ok      day08   0.003s
1
2
3
4
5

# 多个类型对应一个接口

type Q interface {
	q()
}
type X struct{}
type Y struct{}

func (x X) q() {
	fmt.Println("我是X的q")
}
func (y Y) q() {
	fmt.Println("我是Y的q")
}
func Test_05(t *testing.T) {
	var x Q = X{}
	var y Q = Y{}
	x.q()
	y.q()
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[root@CentOS day08]# go test -run Test_05
我是X的q
我是Y的q
PASS
ok      day08   0.002s
1
2
3
4
5

# 接口嵌套

type AA interface {
	aa()
}
type BB interface {
	AA
	bb()
}
type CC struct{}

func (c CC) aa() {
	fmt.Println("aa")
}
func (c CC) bb() {
	fmt.Println("bb")
}

func Test_06(t *testing.T) {
	c := CC{}
	var a AA = c
	var b BB = c
	a.aa()
	b.aa()
	b.bb()
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[root@CentOS day08]# go test -run Test_06
aa
aa
bb
PASS
ok      day08   0.002s
1
2
3
4
5
6

# 空接口

没有定义任何的方法,所以任何类型都实现了空接口,所以任何类型都可以定义为空接口

func Test_07(t *testing.T) {
	var a interface{} = 1
	var b interface{} = "abc"
	fmt.Printf("%T,%v\n", a, a)
	fmt.Printf("%T,%v\n", b, b)
}
1
2
3
4
5
6
[root@CentOS day08]# go test -run Test_07
int,1
string,abc
PASS
ok      day08   0.002s
1
2
3
4
5

# 应用场景

# 接收参数
func Fn(v interface{}) {
	fmt.Printf("%T,%v\n", v, v)
}
func Test_08(t *testing.T) {
	Fn("ABC")
	Fn(123)
}
1
2
3
4
5
6
7
[root@CentOS day08]# go test -run Test_08
string,ABC
int,123
PASS
ok      day08   0.002s
1
2
3
4
5
# 值为任意类型的键值对 map
func Test_09(t *testing.T) {
	m := map[string]interface{}{
		"name":   "xxcheng",
		"sex":    "男",
		"age":    18,
		"weight": 59.9,
	}
	for key, value := range m {
		fmt.Printf("key:%s\t value:%#v\t value-type:%T\n", key, value, value)
	}
}
1
2
3
4
5
6
7
8
9
10
11
[root@CentOS day08]# go test -run Test_09
key:age  value:18        value-type:int
key:weight       value:59.9      value-type:float64
key:name         value:"xxcheng"         value-type:string
key:sex  value:"男"      value-type:string
PASS
ok      day08   0.002s
1
2
3
4
5
6
7
上次更新: 2023/07/11, 16:47:49
golang夯实基础第七天

← golang夯实基础第七天

最近更新
01
Go:GMP模型深入理解
01-10
02
rpc学习:进阶到gRPC
01-04
03
配置
12-12
更多文章>
Theme by Vdoing | Copyright © 2019-2024 xxcheng | 浙ICP备19024050号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式