go语言函数/方法入参对象方法 接口interface约束示例

go语言使用泛型接口约束可以约束指定的对象参数 必须具备指定的方法 或者必须实现了指定的接口 1个或者多个接口(通过接口继承实现), 这个在面向api的接口编程中应用非常广泛,也非常实用,废话不多说,直接上代码:

泛型约束 接口 方法 接口继承 示例代码

Go 复制代码
//文件名 person.go
package genricargs

import "fmt"

// 泛型接口约束方法/函数形参,可以约束形参对象必须拥有指定的方法才能调用,
// 如 func SpeechDemo2[T interface {Speech() string; Exam()}](people T)
// 形参方法约束如果有多个可以每个一行或者在当行使用 分号 ; 隔开
// 这里的[T interface {Speech() string; Exam()}]约束的是 T中的方法,只要T中有这里指定的方法即可,
// 如果 T后面跟的 interface{ 方法定义1,方法定义2} 这表示T必须具备指定的方法, 如 [T interface {Speech() string; Exam()}]
// 如果 T后面跟的是接口,则说明T必须是实现指定的接口的对象, 如  [T Ability]
// 如果需要约束某个对象必须具备多个接口,则可以是继承的方式创建一个新的接口 然后继承需要约束的接口, 如 [T AB] 这里的AB就继承了2个接口 见后面代码

// 定义对象 用来存放数据
type Person struct {
	Name string `json:"name"`
	Age  int    `json:"age"`
}

// 定义Ability能力接口
type Ability interface {
	Speech() string //演讲方法
	Swim()          //游泳方法
}

// 为对象Person实现Ability接口
func (p *Person) Speech() string {
	return fmt.Sprintf("%v正在演讲", p.Name)
}
func (p *Person) Swim() {
	fmt.Printf("%v正在游泳\n", p.Name)
}

// Person的其他普通方法
func (p *Person) Exam() {
	fmt.Printf("%v正在考试\n", p.Name)
}

// 演讲测试
func SpeechDemo[T interface {
	Speech() string
	Swim()
}](people T) {
	str := people.Speech() // 因为T约束了这个people必须具备Speech这个方法,所以这里才可以直接调用
	fmt.Println(str)
	people.Swim()
}

// 约束people必须是拥有 Speech()和Exam()方法的对象,
func SpeechDemo2[T interface {
	Speech() string
	Exam()
}](people T) {
	str := people.Speech() // 因为T约束了这个people必须具备Speech这个方法,所以这里才可以直接调用
	fmt.Println(str)
	people.Exam()
}

// 这个当前的Person对象中没有Flight()方法, 调用直接编译错误
func SpeechDemo3[T interface {
	Speech() string
	Flight()
}](people T) {
	str := people.Speech() // 因为T约束了这个people必须具备Speech这个方法,所以这里才可以直接调用
	fmt.Println(str)
	people.Flight()
}

// 泛型参数直接约束接口, 当然这里的接口可以是多个 使用|分隔即可 ,如 [T Aaa| Bbb ]表示T必须是实现了Aaa或者Bbb
func SpeechDemo4[T Ability](people T) {
	str := people.Speech() // 因为T约束了这个people必须具备Speech这个方法,所以这里才可以直接调用
	fmt.Println(str)
	people.Swim()
	// people.Flight() //这行代码 直接编译错误 因为Ability接口中没有这个方法
}

type Bbb interface {
	Flight()
}

// 继承Ability和Bbb接口
type AB interface {
	Ability
	Bbb
}

// 这里使用了接口继承的方式来约束这里的people必须实现了 Ability接口和Bbb接口
func SpeechDemo5[T AB](people T) {
	str := people.Speech() // 因为T约束了这个people必须具备Speech这个方法,所以这里才可以直接调用
	fmt.Println(str)
	people.Swim()
	people.Flight()
}

单元测试用例

Go 复制代码
// person_test.go
package genricargs

import (
	"testing"
)

// 单元测试用例
// TestXxx和 ExampleXxx使用示例
// 这2种方法的区别在于Test需要带上参数 t *testing.T 而ExampleXxx则不需要, 带参数的TestXxx可以调用 t里面的一系列方法
// 他们都可以使用Output来指定期望的输出
// testing官方手册  https://pkg.go.dev/testing@go1.22.3
// 测试运行命令
// go test -run "        # Run all tests.
// go test -run Foo       # Run top-level tests matching "Foo", such as "TestFooBar".
// go test -run Foo/A=    # For top-level tests matching "Foo", run subtests matching "A=".
// go test -run /A=1      # For all top-level tests, run subtests matching "A=1".
// go test -fuzz FuzzFoo  # Fuzz the target matching "FuzzFoo"
//
// 使用 TestXxx语法进行测试
func TestSpeechDemo(t *testing.T) {
	p1 := &Person{Name: "John", Age: 18}
	SpeechDemo(p1)  // 这里需要自己判断测试是否通过 如果未通过使用 t.Fatalf来格式化输出异常信息(或者函数抛异常也会是失败), 否则使用 t.Logf
	t.Fatal("测试失败") //直接指定这个测试是失败的 这时就会输出所有的控制台结果 包括被测试对象中使用fmt.Print打印的结果
	t.Log("abc ok")

	// 点击函数上方的 run test 这个会输出以下信息
	// go test -timeout 30s -run ^TestSpeechDemo$ tekin.cn/golearn/src/interface/genric_args

	// John正在演讲
	// John正在游泳
	// --- FAIL: TestSpeechDemo (0.00s)
	//
	//	/xxx/golang_learn_mod/src/interface/genric_args/person_test.go:29: 测试失败
	//
	// FAIL
	// FAIL	tekin.cn/golearn/src/interface/genric_args	0.281s
	// FAIL
}

// 使用 ExampleXxx方法进行测试
func ExampleSpeechDemo2() {
	p := &Person{Name: "Alex", Age: 20}
	SpeechDemo2(p)
	// output:Alex正在演讲
	// Alex正在考试
}

func ExampleSpeechDemo3(t *testing.T) {
	// p := &Person{Name: "Alex", Age: 20}
	// SpeechDemo3(p) //这里直接报语法错误 无法编译 因为 参数p缺少方法 Flight
	// output: T (type *Person) does not satisfy interface{Flight(); Speech() string} (missing method Flight)
}
相关推荐
007php00710 小时前
GoZero 上传文件File到阿里云 OSS 报错及优化方案
服务器·开发语言·数据库·python·阿里云·架构·golang
高 朗11 小时前
【GO基础学习】基础语法(2)切片slice
开发语言·学习·golang·slice
IT书架12 小时前
golang面试题
开发语言·后端·golang
醒过来摸鱼18 小时前
【Golang】协程
开发语言·后端·golang
灼华十一20 小时前
算法编程题-排序
数据结构·算法·golang·排序算法
宋发元20 小时前
Go语言使用 kafka-go 消费 Kafka 消息教程
golang·kafka·linq
宋发元21 小时前
Go消费kafka中kafkaReader.FetchMessage(ctx)和kafkaReader.ReadMessage(ctx)的区别
golang·kafka·linq
祁许1 天前
【Golang】手搓DES加密
开发语言·golang·密码学
凡人的AI工具箱1 天前
15分钟学 Go 实战项目六 :统计分析工具项目(30000字完整例子)
开发语言·数据库·人工智能·后端·golang
王大锤43911 天前
golang通用后台管理系统10(退出登录,注销token)
golang