1

Go语言接口在实际应用中的一些思维过程 (语言转型同学可看)

 1 year ago
source link: https://studygolang.com/articles/35928
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Go语言接口在实际应用中的一些思维过程 (语言转型同学可看)

cheney2022 · 大约6小时之前 · 16 次点击 · 预计阅读时间 2 分钟 · 大约8小时之前 开始浏览    

在一个基于缓冲和非缓冲输出的代码测试过程中, 一些接口类型使用时的思考过程(超详细)

package main

import (
    "bufio"
    "fmt"
    "os"
)

func main() {

    // io包中接口的概念

    fmt.Fprintf(os.Stdout, "%s\n", "这些文字不经过缓冲")

    // 通过bufio标准库新建一个io.Writer接口类型变量, 此变量在缓冲中?
    /**
     * bufio中的Writer类型(结构体) 实现了io.Writer接口对象提供的缓冲.
     * 如果在向一个Writer类型值写入时遇到了错误, 该对象不再接受任何数据,且所有写操作都会返回该错误
     * 再说数据都写入后, 调用者有义务调用Flush方法以保证所有的数据都交给了下层的io.Writer
     *
     * bufio.NewWriter() 返回了一个bufio.Writer的指针
     * 调用逻辑:
     *  bufio.NewWriter 需要传入一个实现io.Writer接口的变量
     *  此时传入的值是 os.Stdout
     *         >os.Stdout是什么 它是os.File的指针, 溯源代码可以发现os.Stdout 的文件描述符是1 即输出他的变量构建通过os中的NewFile创建了一个&File
     *         >那此时我们想到传参其实是需要是实现io.Writer类型的变量, os.File是否实现了io.Writer 我们看一看
     *         >回想go的接口实现, 当一个变量被要求是指定接口类型时, 此变量类型上一定定义了接口中要求的方法, 此例中, io.Writer要求实现了Write方法签名, 此前名要求一个byte切片类型并返回一个整型和错误
     *         >回到第一步分析, os.Stdout是一个os.File的指针, 那么os.File类型的指针变量是否实现了io.Writer接口?
     *         >针对上一行问题引入io标准库和os标准库的概念:
     *         >io库提供了对I/O原语的基本接口, 可以理解为将这些原语的现有实现(如os库中的原语) 包装到抽象功能的公共接口中, 以及一些其他的相关原语
     *         >os库为操作系统功能提供了一个独立于平台的接口. 设计类似于Unix, 进款错误处理类似于Go; 失败的调用返回错误类型的值,而不是错误号.os接口旨在在所有操作系统中保持统一的接口形态.通常不可用的功能出现在系统特定的包系统调用中
     *         > OK, 了解完以上两个概念以后, 我们并没有看到问题得到解释
     *         > 那我们只能回到代码寻找一些证据, 那么我们可以找到io库中的Writer是一个接口,此接口要求变量是一个实现了Write方法的类型
     *         > os.File类型上定义了Write方法此方法的签名结构和io.Writer要求的结构一致, 回想我们对Go语言接口实现的认知, Go语言的接口是被隐式实现的, 即只要实现了接口中的方法就实现了改接口
     *         > 综上, 解释了为什么os.Stdout 是 io.Writer 接口类型 (有时候直观上看不到继承, 尤其是从面向对象来的同学可能会很诧异这个类型是怎么被实现的, 这里就完美的做一个思维上的理解)
     */
    buf := bufio.NewWriter(os.Stdout)
    fmt.Fprintf(buf, "%s\n", "这些文字在缓冲区中")

    // 此时如果不调用buf.Flush 则所有数据仍然在缓冲中, 并未将数据刷给下层的io.Writer
    buf.Flush() //  Flush方法将缓冲区中的数据写入下层的io.Writer接口
}

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK