当一个接口只被一个单一的具体类型实现时有一个例外,就是由于它的依赖,这个具体类型
不能和这个接口存在在一个相同的包中。这种情况下,一个接口是解耦这两个包的一个好方
式。
func sq(in <-chan int) <-chan int {
out := make(chan int)
go func() {
//异步的从in获取数据,开始是阻塞的,遍历写入out,当gen调用close(out)后就会不在阻塞等待in的数据
for n := range in {
out <- n * n
}
// 通知main goroutine的for 通道数据写入完,读取完就可以了,不用阻塞了
close(out)
}()
return out
}
测试:
package main
import (
"fmt"
)
// gen函数,nums表示多个int类型数据,多参数 返回一个只读取的通道, 不会阻塞
func gen(nums ...int) <-chan int {
out := make(chan int)
go func() {
// 写入所有数据,然后关闭通道,写入一个之后等待消费者消费后,才可以再次写入
for _, n := range nums {
out <- n
}
// close 后不能写入,其他goroutine读取out的数据完之后就会退出不在阻塞
close(out)
}()
return out
}
func sq(in <-chan int) <-chan int {
out := make(chan int)
go func() {
//异步的从in获取数据,开始是阻塞的,遍历写入out,当gen调用close(out)后就会不在阻塞等待in的数据
for n := range in {
out <- n * n
}
// 通知main goroutine的for 通道数据写入完,读取完就可以了,不用阻塞了
close(out)
}()
return out
}
func main() {
c := gen(2, 3)
out := sq(c)
// 类似于JAVA CompleteFuture.thenApply ..等
for i := range out{
fmt.Println(i)
}
}
同样的sq函数输入,输出类似,可以多次调用该节点
func main() {
c := gen(2, 3)
out := sq(c)
out = sq(out)
// 类似于JAVA CompleteFuture.thenApply ..等
for i := range out{
fmt.Println(i)
}
}
以下答案由GPT-4.5Plus大模型(语音)与博主A努力中.......共同编写:
是的,这是接口的一个重要作用 - 解耦。当接口只有一个实现,但这个实现与接口不能在同一个包中时,接口可以用来解耦两个包之间的依赖。
举个例子:
包A:
java
public interface DataProcessor {
void processData();
}
包B:
java
public class ConcreteDataProcessor implements DataProcessor {
public void processData() {
// 处理数据的逻辑
}
}
如果没有DataProcessor接口,包A要使用ConcreteDataProcessor,就必须依赖包B。这样包A和包B就紧密耦合了。
有了接口后,情况就不同了:
包A:
java
public class ProcessorRunner {
private DataProcessor processor;
public ProcessorRunner(DataProcessor p) {
this.processor = p;
}
public void runProcessor() {
processor.processData();
}
}
现在包A只依赖包A自己的DataProcessor接口,并不依赖包B。在运行时,可以向ProcessorRunner传递包B的ConcreteDataProcessor实例,这样就解耦了两个包之间的依赖。
所以,当接口只有一个实现,但实现与接口不能在同一个包时,接口可以通过解耦包之间的依赖关系,提高系统的灵活性和可扩展性。接口使得两个包可以松散耦合,不会因为一个具体的实现类而变得紧密耦合。
这是设计良好的软件系统的一个关键点 - 高内聚松耦合。接口是实现该目标的重要手段之一。