• 技术文章 >后端开发 >Golang

    go fmt命令的作用是什么

    青灯夜游青灯夜游2023-01-28 11:42:37原创116

    在go语言中,“go fmt”命令主要是用来帮开发者格式化所写好的代码文件。“go fmt”命令会按照Go语言代码规范格式化指定代码包中的所有Go语言源码文件的代码,所有Go语言源码文件即包括命令源码文件、库源码文件和测试源码文件。“go fmt”命令只会格式化被直接保存在指定代码包对应目录下的Go语言源码文件。

    本教程操作环境:windows7系统、GO 1.18版本、Dell G3电脑。

    go fmt命令介绍

    对于一门编程语言来说,代码格式化是最容易引起争议的一个问题,不同的开发者可能会有不同的编码风格和习惯,但是如果所有开发者都能使用同一种格式来编写代码,那么开发者就可以将主要精力放在语言要解决的问题上,从而节省开发时间。

    Go语言的开发团队制定了统一的官方代码风格,并且推出了 gofmt 工具(gofmt 或 go fmt)来帮助开发者格式化他们的代码到统一的风格。

    gofmt 是一个 cli 程序,会优先读取标准输入,如果传入了文件路径的话,会格式化这个文件,如果传入一个目录,会格式化目录中所有 .go 文件,如果不传参数,会格式化当前目录下的所有 .go 文件。

    而Go语言中还有一个go fmt命令,go fmt命令是 gofmt 的简单封装。

    1.png

    go fmt命令主要是用来帮你格式化所写好的代码文件【很多第三方集成软件都是使用了go fmt命令】

    使用:

    go fmt <文件名>.go

    使用go fmt命令,更多时候是用gofmt,而且需要参数-w,否则格式化结果不会写入文件。gofmt -w src,可以格式化整个项目。

    参数介绍

    go fmt与gofmt

    go fmt命令会按照Go语言代码规范格式化指定代码包中的所有Go语言源码文件的代码,所有Go语言源码文件即包括命令源码文件、库源码文件和测试源码文件。注意,当代码包还有子代码包时,子代码包中的Go语言源码文件是不包含在内的。也就是说,go fmt命令只会格式化被直接保存在指定代码包对应目录下的Go语言源码文件。

    与go doc命令和godoc命令的关系类似,go fmt命令是gofmt命令的简单封装。go fmt命令本身可以接受两个标记。标记-n可以让命令程序仅打印出内部使用的gofmt命令及其标记和参数而不真正执行它。标记-x则会使命令程序既打印又执行这个命令。在go fmt命令程序内部,会在其调用的gofmt命令后面加上标记-l和-w,并以指定代码包中的所有Go语言源码文件的路径作为参数,就像这样:

    hc@ubt:~$ go fmt -n pkgtool
    gofmt -l -w golang/goc2p/src/pkgtool/envir.go golang/goc2p/src pkgtoolenvir_test.go golang/goc2p/src/pkgtool/fpath.go golang/goc2p/src/pkgtool ipath.go golang/goc2p/src/pkgtool/pnode.go golang/goc2p/src/pkgtool/util.go golang/goc2p/src/pkgtool/util_test.go

    注意,作为gofmt命令参数的Go语言源码文件的路径是相对的,而不是绝对的。不过这只是为了让参数看起来更短一些而已。所以,当我们直接执行gofmt命令的时候,使用源码文件的绝对路径作为参数也是没有问题的。实际上,任何Go源码文件或包含有Go语言源码文件的目录的相对路径或绝对路径都可以作为gofmt命令的参数。当使用包含有Go语言源码文件的目录的绝对路径或相对路径作为参数时,gofmt命令会把在这个目录下的Go语言源码文件作为目标源码文件。

    go fmt命令程序内部在执行gofmt命令时加入的标记是固定的。如果我们想使用与之不同的标记集合就必须直接使用gofmt命令了。现在我们来看一下gofmt命令可接受的所有标记。如下表。

    表0-13 gofmt命令的标记说明

    标记名称标记描述
    -cpuprofile把CPU概要写入指定文件。文件的路径应该作为此标记的值。
    -d显示格式化前后的不同(如果有的话),而不是直接格式化那些代码。
    -e报告目标源码文件中的所有错误。默认情况下,仅会显示前10个错误。
    -l仅把那些不符合格式化规范的、需要被命令程序改写的源码文件的绝对路径打印到标准输出。而不是把改写后的全部内容都打印到标准输出。
    -r添加形如“a[b:len(a)] -> a[b:]”的重写规则。如果我们需要自定义某些额外的格式化规则,就需要用到它。规则字符串应该作为此标记的值。
    -s简化文件中的代码。
    -w把改写后的内容直接写入到文件中,而不是作为结果打印到标准输出。

    看过上表中的信息,我们就很容易理解go fmt命令的行为了。因为它在内部执行了gofmt命令,并加入了标记-l和-w。这会使命令程序打印需要改写的文件的绝对路径到标准输出,并且直接把格式化后的内容写入到原始文件中。在默认情况下,gofmt命令会把格式化后的内容直接打印到标准输出上。

    实际上,命令程序会把目标源码文件中的内容解析成抽象语法树。当在解析过程中发现语法错误时,命令程序就会显示错误提示信息并退出。在默认情况下,目标源码文件中的语法错误不会全部被显示出来。我们可以加入标记-e以使命令程序打印出全部错误到标准输出。

    自定义改写操作

    在默认情况下,gofmt命令对Go语言源码文件的改写操作包括如下几个方面:

    如果想自定义额外的改写操作,需要使用-r标记。-r标记的值中必须包含“->”,比如a[b:len(a)] -> a[b:]。“->”的左边应该是需要被替代的表达式的示例,而右边则应该是用来替代“->”左边表达式的表达式的示例。

    如果我们使用标记-r,那么命令程序在解析源码文件之前会将此标记值中的被替换表达式和替换表达式分别解析为抽象语法树的表达式节点。如果解析不成功,也就意味着无法进行后续的替换操作,命令程序会在打印错误提示信息后退出。如果解析成功,那么命令程序会在解析源码文件成功之后进行表达式替换操作。命令程序会寻找该源码文件的抽象语法树中与被替换表达式相匹配的节点,并用替换表达式替换之。gofmt命令已支持但不限于如下自定义替换操作:

    代码简化操作

    当我们在执行gofmt命令时加入了标记-s,命令程序会在目标源码文件中寻找可以简化的代码并简化它。简化操作包括:

    这些操作基本上都是出于尽量使用Go语言的语法糖已达到减少代码量的目的。我们在编写Go语言代码的时候应该直接使用这些语法糖而不应该依赖使用gofmt命令来简化。这里所说的Go语言的语法糖,我们在第3章中已经有所介绍。

    我们在本小节中详细介绍了go fmt命令和gofmt命令。下面我们再汇总一下这两个命令可以为我们做的事情。如下表。

    表0-14 go fmt命令和gofmt命令的功能

    功能go fmt命令gofmt命令
    格式化代码
    列出不规范的源码文件
    自动改写源码文件
    显示对比信息×
    提示全部错误×
    简化代码×
    自定义替换/重构辅助×
    CPU概要记录×

    最后,值得一提的是,当我们执行gofmt命令且没有加任何参数的时候,该命令将会进入到交互模式。在这种模式下,我们可以直接在命令行界面中输入源码,并以Ctrl-d结束。在Linux操作系统下,Ctrl-d代表EOF(End Of File,中文译为文件结束符)。需要注意的是,如果在一行的中间按下Ctrl-d,则表示输出“标准输入”的缓存区,所以这时必须连续按两次Ctrl-d。另外,在Windows操作系统下,Ctrl-z代表EOF,所以需要以Ctrl-z结束。在这之后,gofmt命令会像从源码文件中读取源码那样从命令行界面(也称为标准输入)读取源码,并在格式化后将结果打印到命令行界面(也称为标准输出)中。示例如下:

    hc@ubt:~$ gofmt -r='fmt.Println(a)->fmt.Printf("%s\n", a)'
    if a=="print" {fmt.Println(a)}                            <----- 在此行的末尾键入回车和Ctrl-d。
    warning: rewrite ignored for incomplete programs          <----- 此行及以下就是命令输出的内容。
    if a == "print" {
            fmt.Println(a)
    }

    由上述示例可知,我们可以使用gofmt命令的交互模式格式化任意的代码片段。虽然会显示一行警告信息,但是格式化后的结果仍然会被打印出来。并且,在交互模式下,当我们输入的代码片段不符合Go语言的语法规则时,命令程序也会打印出错误提示信息。在其它方面,命令程序在交互模式与普通模式下的行为也是基本一致的。

    【相关推荐:Go视频教程编程教学

    以上就是go fmt命令的作用是什么的详细内容,更多请关注php中文网其它相关文章!

    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
    专题推荐:go语言 Golang
    上一篇:go clean有什么用 下一篇:自己动手写 PHP MVC 框架(40节精讲/巨细/新人进阶必看)

    相关文章推荐

    • go语言中append()怎么用• go语言中反射三定律是什么• go语言依赖注入是什么• go语言有没有注解• go语言中切片怎么增删元素• go语言面向什么
    1/1

    PHP中文网